rollup打包js的注意点

栏目: JavaScript · 发布时间: 7年前

内容简介:rollup比较适合打包js的sdk或者封装的框架等,例如,vue源码就是rollup打包的。webpack比较适合打包一些应用,例如SPA或者同构项目等等。最近我们对rollup小试牛刀了一下。简单分享一些注意事项吧。rollup基础知识及插件的一些使用,网上有不少资料,可以去查阅。rollup中文网:

前言

rollup比较适合打包js的sdk或者封装的框架等,例如,vue源码就是rollup打包的。webpack比较适合打包一些应用,例如SPA或者同构项目等等。最近我们对rollup小试牛刀了一下。简单分享一些注意事项吧。

rollup基础

rollup基础知识及插件的一些使用,网上有不少资料,可以去查阅。

rollup中文网: https://www.rollupjs.com/guide/zh#-danger-zone-

问题记录吧

下面主要记录一下rollup使用过程中的一些报错及解决方案吧。

错误一:

You must supply options.name for IIFE bundles

出现这个报错,是要在options中指定name,例如如下:

output: {
    file: resolve(`js/haorooms.${type}.js`),
    format: type,
    name: 'haorooms',
    banner
  },

错误二

[!] (commonjs plugin) SyntaxError: Unexpected token

出现这个问题,可能有几个原因

1、rollup-plugin-commonjs未引入,或者加载循序不对

我们知道,webpack loader是有加载循序的(从右到左,从下到上),rollup虽然没有严格的加载循序,但是我通常是将commonjs放到babel编译之后。如下:

babel({
      exclude: 'node_modules/**', // 排除node_modules 下的文件
      runtimeHelpers: true
    }),
    commonjs(),

2、缺少babel类 我按照babel类熟悉编译插件作为这个项目的依赖。

npm install --save-dev babel-plugin-transform-class-properties

.babelrc配置如下:

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": ["transform-runtime", "external-helpers","transform-class-properties"]
}

注:上面的配置是babel 7.0以下的方式,假如babel7.0以上,用另外的方式配置,参见: https://babeljs.io/docs/en/v7-migration

https://blog.zfanw.com/babel-js/

错误三

code: 'BAD_BUNDLE_TRANSFORMER', plugin: 'uglify'

这个问题比较坑爹,其实我用rollup打包demo代码是没有问题的,但是打包我的js就有问题了,好奇怪,后来我发现是swiper的问题,因为我依赖了swiper。关于swiper打包,在webpack中也有问题,通常babel打包之后,并不会把swiper的es6语法转换。有时候webapck也会报错,大致是

dom7 undefined ..

webpack解决方案如下:

resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'swiper': 'swiper/dist/js/swiper.js',
      '@': resolve('src')
    }
  },

指定一个别名

但是发现rollup中好像没有这个方式,无奈,我在引入swiper的时候如下处理

import Swiper from 'swiper/dist/js/swiper.js'

这样打包的时候就不会有问题了。

错误四

process not defined

这个错误是在打包成功之后,浏览器运行发现的,发现打包之后的代码中有process.env.NODE_ENV

解决方案:

import replace from 'rollup-plugin-replace'

const env = process.env.NODE_ENV
plugins: [
 replace({
      'process.env.NODE_ENV': JSON.stringify(env)
    }),
]

把 process.env.NODE_ENV这个替换掉

rollup 批量打包的方式

我们用rollup打包,一般都会打如下方式

amd – 异步模块定义,用于像RequireJS这样的模块加载器
cjs – CommonJS,适用于 Node 和 Browserify/Webpack
es – 将软件包保存为ES模块文件
iife – 一个自动执行的功能,适合作为<script>标签。(如果要为应用程序创建一个捆绑包,您可能想要使用它,因为它会使文件大小变小。)
umd – 通用模块定义,以amd,cjs 和 iife 为一体

我是用node,循环读取的方式,配置如下:

const babel = require('rollup-plugin-babel')
const node = require('rollup-plugin-node-resolve')
const commonjs = require('rollup-plugin-commonjs')
const json = require('rollup-plugin-json')
const replace = require('rollup-plugin-replace')
const uglify = require('rollup-plugin-uglify')
// 新增 rollup-plugin-postcss 插件
const postcss = require('rollup-plugin-postcss')
// 新增 postcss plugins
const simplevars = require('postcss-simple-vars')
const nested = require('postcss-nested')
const cssnext = require('postcss-cssnext')
const cssnano = require('cssnano')
const version = process.env.VERSION || require('../package.json').version
const path = require('path')
const fs = require('fs')
const ora = require('ora')
const terser = require('terser')
const zlib = require('zlib')
const spinner = ora('building for production...')
spinner.start()
const rollup = require('rollup')
if (!fs.existsSync('dist')) {
  fs.mkdirSync('dist')
}
function resolve(dir) {
  return path.join(__dirname, '..', dir)
}
const banner =
  '/*!\n' +
  ` * haoroomsjssdk v${version}\n` +
  ` * (c) 2017-${new Date().getFullYear()}\n` +
  ' * Released under the MIT License.\n' +
  ' */'

  // amd – 异步模块定义,用于像RequireJS这样的模块加载器
  // cjs – CommonJS,适用于 Node 和 Browserify/Webpack
  // es – 将软件包保存为ES模块文件
  // iife – 一个自动执行的功能,适合作为<script>标签。(如果要为应用程序创建一个捆绑包,您可能想要使用它,因为它会使文件大小变小。)
  // umd – 通用模块定义,以amd,cjs 和 iife 为一体
const buildArray = ['amd', 'cjs', 'iife', 'umd']

let allConfig = []
const env = process.env.NODE_ENV
let baseConfig = {
  plugins: [
    postcss({
      extensions: ['.css'],
      plugins: [
        simplevars(),
        nested(),
        cssnext({ warnForDuplicates: false }),
        cssnano()
      ]
    }),
    node({
      jsnext: true, // 该属性是指定将Node包转换为ES2015模块
      // main 和 browser 属性将使插件决定将那些文件应用到bundle中
      main: true, // Default: true
      browser: true // Default: false
    }),
    json(),
    babel({
      exclude: 'node_modules/**', // 排除node_modules 下的文件
      runtimeHelpers: true
    }),
    commonjs(),
    replace({
      'process.env.NODE_ENV': JSON.stringify(env)
    }),
    (env === 'production' && uglify())
  ]
}
buildArray.forEach(item => {
  let outputs = {
    input: resolve('src/haorooms.js'),
    output: {
      file: resolve(`js/haorooms.${item}.min.js`),
      format: item,
      name: 'haorooms',
      banner
    }
  }
  allConfig.push(Object.assign({}, baseConfig, outputs))
})

function build (builds) {
  let built = 0
  const total = builds.length
  const next = () => {
    buildEntry(builds[built]).then(() => {
      built++
      if (built < total) {
        next()
      } else {
        spinner.stop()
      }
    }).catch(logError)
  }

  next()
}

function buildEntry (config) {
  const output = config.output
  const { file, banner } = output
  const isProd = /min\.js$/.test(file)
  return rollup.rollup(config)
    .then(bundle => bundle.generate(output))
    .then(({ code }) => {
      if (isProd) {
        const minified = (banner ? banner + '\n' : '') + terser.minify(code, {
          output: {
            ascii_only: true
          },
          compress: {
            pure_funcs: ['makeMap']
          }
        }).code
        return write(file, minified, true)
      } else {
        return write(file, code)
      }
    })
}

function write (dest, code, zip) {
  return new Promise((resolve, reject) => {
    function report (extra) {
      console.log(blue(path.relative(process.cwd(), dest)) + ' ' + getSize(code) + (extra || ''))
      resolve()
    }

    fs.writeFile(dest, code, err => {
      if (err) return reject(err)
      if (zip) {
        zlib.gzip(code, (err, zipped) => {
          if (err) return reject(err)
          report(' (gzipped: ' + getSize(zipped) + ')')
        })
      } else {
        report()
      }
    })
  })
}

function getSize (code) {
  return (code.length / 1024).toFixed(2) + 'kb'
}

function logError (e) {
  console.log(e)
}

function blue (str) {
  return '\x1b[1m\x1b[34m' + str + '\x1b[39m\x1b[22m'
}

build(allConfig)

运行的时候直接如下:

cross-env NODE_ENV=production node 上面的文件名

备注:cross-env 可以指定环境变量等

另外一种方式是用npm run all

参见地址: https://www.npmjs.com/package/npm-run-all

可以用这个来运行多个npm 命令,来达到运行一次,打包所有的功能!


以上所述就是小编给大家介绍的《rollup打包js的注意点》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Design and Analysis of Distributed Algorithms (Wiley Series on P

Design and Analysis of Distributed Algorithms (Wiley Series on P

Nicola Santoro / Wiley-Interscience / 2006-10-27 / USD 140.95

This text is based on a simple and fully reactive computational model that allows for intuitive comprehension and logical designs. The principles and techniques presented can be applied to any distrib......一起来看看 《Design and Analysis of Distributed Algorithms (Wiley Series on P》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具