# 一、开始

Rollup (opens new window) 是一个JavaScript模块打包器,其使用ES6规则进行打包,天然具有tree-shaking特性,且体积轻巧,打包后文件可读性高。VueVue RouterVuex等库均使用Rollup打包。

下面从一个简单的例子开始,代码地址在这里 (opens new window)

新建一个项目,在src/index.js中随便写点内容:

console.log('How are you?')

安装rollup,然后执行:

rollup src/index.js -f umd -o dist/bundle.js

dist/bundle.js中即可查看到打包后的文件。

# 二、命令行参数

下面是rollup常用的命令行的参数:

  • -f--format的缩写,它表示生成代码的格式,取值有amdcjssystemesmiifeumd。关于打包方式的差异可以参考这里 (opens new window)
  • -o-o指定了输出的路径,比如上面的dist/bundle.js
  • -c。指定rollup的配置文件。默认为rollup.config.js
  • -w。监听源文件是否有改动,如果有改动,重新打包。
  • -n--name的缩写,是打包后的模块名称,同一页面的其他脚本可以访问它。也可以在配置文件的output.name中定义

# 三、配置文件

新建文件rollup.config.js

export default {
  input: ["./src/index.js"],
  output: {
    file: "./dist/bundle.js",
    format: "umd",
    name: "myBundle",
  },
  external: ["vue"],
};
  • input表示入口文件的路径(老版本为entry,已经废弃)
  • output表示输出文件的内容,它允许传入一个对象或一个数组,当为数组时,依次输出多个文件,它包含以下内容:
    • output.file:输出文件的路径(老版本为dest,已经废弃)
    • output.format:输出文件的格式
    • output.banner:文件头部添加的内容
    • output.footer:文件末尾添加的内容
  • external打包时要排除掉的模块

# 四、插件

Rollup只提供了最核心的打包功能,很多其他功能需要插件实现。

# 1. @rollup/plugin-node-resolve (opens new window)

Rollup不识别node_modules的模块引入,比如import answer from "the-answer",所以需要resove插件解决。

# 2. @rollup/plugin-commonjs (opens new window)

rollup打包时只支持ES6的模块导入导出方式,即export/import,对于CommonJS方式导出的包,需要使用@rollup/plugin-commonjs解决。

# 3. @rollup/plugin-babel (opens new window)

目前很多浏览器不完全支持ES6,所以需要将项目中的ES6语法转为ES5,这就用到了babel插件。

注意要同时配置.babelrc文件,并且安装@babel/core@babel/preset-env插件。

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": false,
      }
    ]
  ]
}

# 4. @rollup/plugin-json (opens new window)

使用json插件可以在代码中直接引用json文件,比如

import json from '../package.json'

console.log(json.name)

# 5. rollup-plugin-terser (opens new window)

该插件可以压缩打包文件。

# 6. rollup-plugin-replace (opens new window)

该插件用来替换变量:

import replace from '@rollup/plugin-replace'
// ...

plugins: [
  replace({
    preventAssignment: true,
    values: {
      __VERSION__: JSON.stringify(pkg.version),
    },
  }),
]

// ...

为了防止替换过程中,将something=false替换成false=false,引发错误的问题,可以将preventAssignment设置为true

# 五、Demo地址

这里有个简单的例子 (opens new window),你可以clone下来,然后执行npm installnpm run build查看打包结果。

项目 (opens new window)中还包含了一些自定义插件 (opens new window)

# 六、Rollup原理

Rollup分为build(构建)阶段和output generate(输出生成)阶段。主要过程如下:

  • 获取入口文件的内容,包装成module,生成抽象语法树
  • 对入口文件抽象语法树进行依赖解析
  • 生成最终代码
  • 写入目标文件

# 七、Rollup与Webpack

Rollup优势:

  • 基于ES6,支持tree shaking
  • 冗余代码少,执行快
  • 打包结果依然完全可读

Rollup缺陷:

  • 不支持热更新
  • 对于commonjs模块,需要用插件读成ES6代码后再处理
  • umdiife格式无法对公共代码进行拆分,因为自执行函数会把所有的模块都放到一个函数中,并没有像webpack一样有一些引导代码,所以没有办法做到代码拆分

# 八、相关资料

  1. Rollup文档 (opens new window)
  2. 文章中的例子 (opens new window)
  3. 一文带你快速上手Rollup (opens new window)
  4. Rollup使用 (opens new window)
  5. 从0到1解读rollup Plugin (opens new window)
  6. rollup实践系列之从0到1手写rollup (opens new window)
  7. 从rollup初版源码学习打包原理 (opens new window)
  8. estree (opens new window)
  9. 原来rollup这么简单之rollup.rollup篇 (opens new window)
  10. 使用 Acorn 来解析 JavaScript (opens new window)