跟着官方文档学 rollup

273 阅读13分钟

Rollup是什么?

Rollup 是一个用于 JavaScript 的模块打包工具,它将小的代码片段编译成更大、更复杂的代码,例如库或应用程序。它使用 JavaScript 的 ES6 版本中包含的新标准化代码模块格式,而不是以前的 CommonJS 和 AMD 等特殊解决方案。ES 模块允许你自由无缝地组合你最喜欢的库中最有用的个别函数。这在未来将在所有场景原生支持,但 Rollup 让你今天就可以开始这样做。

起步

前置要求:

Rollup 3:

  • Node版本要求:请确保你的 Node 版本至少为14.18.0,并更新所有 Rollup 插件到最新版本。

全局安装

全局安装将使 Rollup 可以作为全局命令工具使用。使用命令行工具运行 npm install --global rollup 简写: npm i -g rollup

快速体验

由于Rollup 可以静态分析你导入的代码,并将排除任何实际上没有使用的内容(Tree-Shaking),
在快速体验的时候,我们都会去调用或者输出下,目的是让rollup去编译,以便我们去感受。

对于浏览器:

(作为<script src="xxx.js">引入使用)

# 编译为包含自执行函数('iife')的 <script>。  
rollup main.js --file bundle.js --format iife

将目标文件 main.js 编译为 自执行函数(iife)格式 生成 bundle.js image.png 将编译的文件 bundle.js 引入 index.html 中使用: image.png

对于Node.js

# 编译为一个 CommonJS 模块 ('cjs')  
rollup main.js --file bundle.js --format cjs

image.png

对于浏览器 和 Node.js

UMD格式(兼容格式)

# UMD 格式需要一个包名  
rollup main.js --file bundle.js --format umd --name "myBundle"

image.png

如果在使用 rollup 遇到 Error: Cannot find module 'node:process', 可能是node版本太低导致(Node版本至少为14.18.0),报错如下:

image.png

本地安装

在团队或分布式环境中工作时,将 Rollup 添加为 本地 依赖可能是明智的选择。本地安装 Rollup 可以避免多个贡献者单独安装Rollup的额外步骤,并确保所有贡献者使用相同版本的Rollup。

用 npm 安装: npm install rollup --save-dev
Yarn 安装: yarn -D add rollup

安装完成后,通常为了避免频繁的输入打包命令,会把命令配置到 package.json 中,作为构建脚本。

{
  "type": "module", // 如果配置文件是 .js 后缀名,这个要配置,后面章节会说明
  "scripts": {
    "build": "rollup --config" // 配置脚本,可以简写成 rollup -c 后面 命令行标志章节有说明
  },
  "devDependencies": {
    "rollup": "^4.2.0"
  }
}

运行 npm run buildyarn build 就可以执行脚本,脚本就可以执行 rollup的命令行 打包。 image.png 这样一旦本地依赖安装完成后,当运行脚本命令时,不管是 NPM 还是 Yarn 都可以找到 Rollup 的可执行文件并执行。


使用教程

使用命令行方式打包

  • 全局安装了rollup:
# 全局安装
npm install rollup --global

运行 rollup 后, 会打印出使用说明。这与运行 rollup --help 或者 rollup -h 相同。 image.png 让我们创建一个简单的项目:

mkdir -p my-rollup-project/src
cd my-rollup-project

首先,我们创建一个名为 foo.js 的模块,它在入口文件中被导入:

    // src/foo.js
    export default "hello world"

创建入口文件 src/main.js, 文件内容:

    // src/main.js
    import foo from './foo'
    export default function() {
        console.log(foo)
    }

打开项目所在的终端 输入命令行命令: rollup src/main.js -f cjs;
-f 选项 (是 --format 的缩写) 指定了产物的类型 — 在本例中是 CommonJS (可以在 Node.js 中运行)。因为我们没有指定输出文件,所以它将直接打印到 stdoutimage.png 你也可以像这样将产物保存为文件:rollup src/main.js -o bundle.js -f cjs; image.png

使用配置文件方式打包

到目前为止,使用命令行方式来打包都挺好的,只是输入命令有点麻烦。为了避免重复输入,我们可以创建一个包含所有必选项的配置文件。配置文件是使用 javascript 编写的,比原始的 cli 更加灵活。

在项目根目录中创建一个名为 rollup.config.mjs 的文件,.mjs后缀名的配置文件,我们要使用 ES模块规范来编写代码;
添加以下代码:

    // rollup.config.mjs
    // ES 模块方式编写的,最后打包成CommonJS模块规范的输出产物。
    export default {
        input: "src/main.js",
        output: {
            file: "bundle.js",
            format: 'cjs' 
        }
    }

image.png 也可以在项目根目录中创建一个名为 rollup.config.cjs 的文件,.cjs后缀名的配置文件,我们使用 CommonJS模块规范来编写代码;例如 module.exports = {/* config */})
添加以下代码:

    // rollup.config.cjs
    // CommonJS 模块规范

    module.exports = {
        input: "src/main.js",
        output: {
            file: "bundle.js",
            format: "cjs"
        }
    }

image.png

使用配置文件,我们使用 rollup --configrollup -c; 命令行标志说明见下方章节 命令行标志以及使用
你可以使用等效的命令行选项 覆盖配置文件中的任何选项,也就是说虽然配置文件中定义了命令行选项,但是我们可以通过打包时输入的命令行命令,来覆盖配置文件中等价的选项。
例如:我们在配置文件中定义了输出的产物文件名叫 bundle.js, 但是我们通过终端使用等效的命令行选项,让它输出产物的文件叫 bundle-2.js

rollup -c -o bundle-2.js # `-o` 等价于 `--file`(曾用名为 "output")

image.png

注意: Rollup本身会处理配置文件,这就是为什么我们可以使用 export default语法的原因 - 代码没有被 Babel 或任何类似的工具转换,因此你只能使用在你当前使用的 Node 版本中支持的 ES2015 功能。

你可以选择指定不同默认的 rollup.config.mjs的配置文件

    rollup --config rollup.config.dev.mjs
    rollup --config rollup.config.prod.mjs

然后可以在脚本中package.json 配置不同的脚本, image.png 可以配合下面的 命令行参数 --environment <values>, 根据不同的环境,注入不同的值; 命令行参数用法 -- 请查看!

配置文件说明

  1. rollup 配置文件可选的,但它们非常强大和方便,因此推荐使用
  2. 配置文件 一个ES模块, 它导出一个默认对象;(也可以使用 requiremodule.exports 编写 CommonJS 模块的配置文件,但是应该将文件扩展名更改为 .cjs。)
  3. 配置文件 通常为:rollup.config.jsrollup.config.mjs;并位于项目的根目录中;

配置文件,其中包含所需的选项:

    // rollup.config.js
    export default {
        input: "./src/main.js",      // 入口
        output: { // 必需的 出口
            file: './dist/bundle.js', // 打包后生成的文件路径及文件名
            format: 'cjs' // 模块格式
        },     
    }

如果配置文件为:rollup.config.js 采用 ES模块方式编写, 打包编译命令使用 rollup --configrollup -c,则会 报错;

原因:Node会尝试将配置文件使用CommonJS模块方式进行加载,即使它可能是一个ES模块(export default{} 方式),除非在命令行中使用 --bundleConfigAsCjs--configPlugin 选项,否则 Rollup 将直接使用 Node 导入该文件。

image.png

解决方式:
方式一: 将配置文件由 rollup.config.js 改为 rollup.config.mjs; image.png

方式二: package.json方式的,在 package.json 中,添加 type: "module"; image.png

方式三: 根据实际情况,增加命令行参数 --bundleConfigAsCjs 或 --configPlugin;
--bundleConfigAsCjs: 此选项将强制将你的配置转译为 CommonJS 。 image.png

rollup的配置文件也可以采用CommonJS模块方式编写,但是应该把文件扩展名更改为: .cjs; image.png

要注意,如果使用 ES模块方式编写配置文件
请注意,使用原生 Node ES模块 时存在一些注意事项,因为 Rollup 将遵循 Node ESM 语义。

原生 Node ES 模块时的注意事项:

  • 获取当前目录: __dirname在原生ES模块中不支持。建议使用 fileURLToPath
    // rollup.config.js
      import {fileURLToPath} from "node:url"
      export default {
          ...,
          external: [
              // 当前所在目录下得绝对路径
              fileURLToPath(new URL('src/some-file.js', import.meta.url))
          ]
      } 
    
    image.png
  • 导入 package.json。
    • 对于 Node 17.5+ 可以使用导入断言 image.png
    • 对于node旧版本,可以使用 createRequire image.png

rollup 配置选项说明

配置文件的配置选项主要分为: 核心功能,进阶功能, 慎用选项,实验选项,观察选项,废弃选项; 具体的配置文件的配置选项说明可以查看中文官网: 配置选项
rollup 配置文件基本结构: image.png rollup配置文件,支持 单文件(单个)配置多文件(多个)配置;

// rollup.config.js

// 可以是数组(即多个输入源)
export default {
    // 核心输入选项
    external,
    input, // 有条件地需要
    plugins,

    // 进阶输入选项
    cache,
    logLevel,
    makeAbsoluteExternalsRelative,
    maxParallelFileOps,
    onLog,
    onwarn,
    preserveEntrySignatures,
    strictDeprecations,

    // 危险区域
    acorn,
    acornInjectPlugins,
    context,
    moduleContext,
    preserveSymlinks,
    shimMissingExports,
    treeshake,

    // 实验性
    experimentalCacheExpiry,
    experimentalLogSideEffects,
    experimentalMinChunkSize,
    perf,

    // 必需(可以是数组,用于描述多个输出)
    output: {
        // 核心输出选项
        dir,
        file,
        format,
        globals,
        name,
        plugins,

        // 进阶输出选项
        assetFileNames,
        banner,
        chunkFileNames,
        compact,
        dynamicImportInCjs,
        entryFileNames,
        extend,
        externalImportAssertions,
        footer,
        generatedCode,
        hoistTransitiveImports,
        inlineDynamicImports,
        interop,
        intro,
        manualChunks,
        minifyInternalExports,
        outro,
        paths,
        preserveModules,
        preserveModulesRoot,
        sourcemap,
        sourcemapBaseUrl,
        sourcemapExcludeSources,
        sourcemapFile,
        sourcemapFileNames,
        sourcemapIgnoreList,
        sourcemapPathTransform,
        validate,

        // 危险区域
        amd,
        esModule,
        exports,
        externalLiveBindings,
        freeze,
        indent,
        noConflict,
        sanitizeFileName,
        strict,
        systemNullSetters,

        // 实验性
        experimentalMinChunkSize
    },

    watch: {
        buildDelay,
        chokidar,
        clearScreen,
        exclude,
        include,
        skipWrite
    }
};
  1. 创建 Rollup配置文件:项目根目录创建 rollup.config.js 文件, 根据需要并定义如上相关配置;
  2. 完成相关操作后,Rollup 可以在项目的根目录中运行;

安装完成后,Rollup 可以在项目的根目录中运行: npx rollup --config 或使用 Yarn: yarn rollup --config,这是用配置文件方式执行(需要定义配置文件);

命令行标志以及使用

命令行标志

终端命令行使用标志的含义,上述我们经常使用:rollup --config --bundleConfigAsCjs, rollup -c --bundleConfigAsCjs,
许多选项都有等效的命令行标志。这些情况下,如果你正在使用配置文件(rollup.config.js),则此处传递的任何参数都将覆盖配置文件。即 命令行传递的参数优先级更高,能覆盖配置文件中的定义。

    -c, --config <filename> 使用此配置文件  
    (如果使用参数但未指定值,则默认为 rollup.config.js)  
    -d, --dir <dirname> 用于块的目录(如果不存在,则打印到 stdout)  
    -e, --external <ids> 排除模块 ID 的逗号分隔列表  
    -f, --format <format> 输出类型(amd、cjs、es、iife、umd、system)  
    -g, --globals <pairs> `moduleID:Global` 对的逗号分隔列表  
    -h, --help 显示此帮助消息  
    -i, --input <filename> 输入(替代 <entry file>)  
    -m, --sourcemap 生成源映射(`-m inline` 为内联映射)  
    -n, --name <name> UMD 导出的名称  
    -o, --file <output> 单个输出文件(如果不存在,则打印到 stdout)  
    -p, --plugin <plugin> 使用指定的插件(可重复)  
    -v, --version 显示版本号  
    -w, --watch 监视产物文件并在更改时重新构建  
    --amd.autoId 基于块名称生成 AMD ID  
    --amd.basePath <prefix> 要预先添加到自动生成的 AMD ID 的路径  
    --amd.define <name> 在 `define` 位置使用的函数  
    --amd.forceJsExtensionForImports 在 AMD 导入中使用 `.js` 扩展名  
    --amd.id <id> AMD 模块的 ID(默认为匿名)  
    --assetFileNames <pattern> 发布资源的名称模式  
    --banner <text> 在产物顶部插入的代码(位于包装器之外)  
    --chunkFileNames <pattern> 发布次要块的名称模式  
    --compact 缩小包装器代码  
    --context <variable> 指定顶级 `this` 值  
    --no-dynamicImportInCjs 将外部动态 CommonJS 导入编写为 require  
    --entryFileNames <pattern> 发布入口块的名称模式  
    --environment <values> 传递给配置文件的设置(请参阅示例)  
    --no-esModule 不添加 __esModule 属性  
    --exports <mode> 指定导出模式(auto、default、named、none)  
    --extend 扩展由 --name 定义的全局变量  
    --no-externalImportAssertions 在 "es" 输出中省略导入断言  
    --no-externalLiveBindings 不生成支持实时绑定的代码  
    --failAfterWarnings 如果生成的构建产生警告,则退出并显示错误  
    --filterLogs <filter> 过滤日志信息  
    --footer <text> 在产物底部插入的代码(位于包装器之外)  
    --no-freeze 不冻结命名空间对象  
    --generatedCode <preset> 使用哪些代码特性(es5/es2015)  
    --generatedCode.arrowFunctions 在生成的代码中使用箭头函数  
    --generatedCode.constBindings 在生成的代码中使用 "const"  
    --generatedCode.objectShorthand 在生成的代码中使用简写属性  
    --no-generatedCode.reservedNamesAsProps 始终引用保留名称作为 props  
    --generatedCode.symbols 在生成的代码中使用符号  
    --no-hoistTransitiveImports 不将中转导入提升到入口块中  
    --no-indent 不缩进结果  
    --inlineDynamicImports 使用动态导入时创建单次打包  
    --no-interop 不包括交互操作块  
    --intro <text> 在产物顶部插入的代码(位于包装器内部)  
    --logLevel <level> 要显示哪种类型的日志  
    --no-makeAbsoluteExternalsRelative 不规范化外部导入  
    --maxParallelFileOps <value> 并行读取的文件数  
    --minifyInternalExports 强制或禁用内部导出的缩小  
    --noConflict 为 UMD 全局生成 noConflict 方法  
    --outro <text> 在产物底部插入的代码(位于包装器内部)  
    --perf 显示性能计时  
    --no-preserveEntrySignatures 避免入口点的门面块  
    --preserveModules 保留模块结构  
    --preserveModulesRoot 将保留的模块放置在根路径下的此路径下  
    --preserveSymlinks 解析文件时不要跟随符号链接  
    --no-sanitizeFileName 不要替换文件名中的无效字符  
    --shimMissingExports 为丢失的导出创建卡扣变量  
    --silent 不打印警告  
    --sourcemapBaseUrl <url> 使用给定的基本 URL 发出绝对源映射 URL  
    --sourcemapExcludeSources 在源映射中不包括源代码  
    --sourcemapFile <file> 指定源映射的包位置  
    --sourcemapFileNames <pattern> 编译后 sourcemap 的命名模式  
    --stdin=ext 指定用于标准输入的文件扩展名  
    --no-stdin 不要从 stdin 读取 "-"  
    --no-strict 不在生成的模块中发出 `"use strict";`  
    --strictDeprecations 抛出有关不推荐使用的功能的错误  
    --no-systemNullSetters 不要将空的 SystemJS setter 替换为 `null`  
    --no-treeshake 禁用除屑优化  
    --no-treeshake.annotations 忽略纯调用注释  
    --treeshake.correctVarValueBeforeDeclaration 在声明之前将变量取消优化  
    --treeshake.manualPureFunctions <names> 手动将函数声明为纯函数  
    --no-treeshake.moduleSideEffects 假设模块没有副作用  
    --no-treeshake.propertyReadSideEffects 忽略属性访问副作用  
    --no-treeshake.tryCatchDeoptimization 不要关闭 try-catch-tree-shaking  
    --no-treeshake.unknownGlobalSideEffects 假设未知的全局变量不会抛出异常  
    --validate 验证输出  
    --waitForBundleInput 等待打包输入文件  
    --watch.buildDelay <number> 节流观察重建  
    --no-watch.clearScreen 重建时不要清除屏幕  
    --watch.exclude <files> 排除要观察的文件  
    --watch.include <files> 限制观察到指定文件  
    --watch.onBundleEnd <cmd> 在 "BUNDLE_END" 事件上运行的 Shell 命令  
    --watch.onBundleStart <cmd> 在 "BUNDLE_START" 事件上运行的 Shell 命令  
    --watch.onEnd <cmd> 在 "END" 事件上运行的 Shell 命令  
    --watch.onError <cmd> 在 "ERROR" 事件上运行的 Shell 命令  
    --watch.onStart <cmd> 在 "START" 事件上运行的 Shell 命令  
    --watch.skipWrite 在监视时不要将文件写入磁盘

命令行参数使用说明

以下命令行标志仅通过命令行界面可用。所有其他标志都对应并覆盖其配置文件等效项。

--bundleConfigAsCjs: 此选项将强制将你的配置转译为CommonJS。 这允许你在配置中使用CommonJS常用的变量/方法,例如__dirnamerequire.resolve,即使配置本身是作为ES模块编写的。

--environment <values>:通过 process.ENV传递其他设置到配置文件。

通过命令行参数传递参数,在项目文件中可以获取到传递过来的变量。

    rollup -c --environment INCLUDE_DEPS,BUILD:production

image.png

其他命令行标识,请查看文档!!click here

Rollup兼容性

  • Rollup 可以通过插件 导入现有的CommonJS模块
  • 发布 ES 模块。 为了确保你的 ES 模块可以立即被处理 CommonJS 的工具,例如 Node.js 和 webpack 使用,你可以使用 Rollup 编译成 UMD 或 CommonJS 格式,然后在 package.json 文件中使用 main 属性指向编译后的版本。如果你的 package.json 文件还有一个 module 字段,那么像 Rollup 和 webpack 2+ 这样的可感知 ES 模块的工具将直接 导入 ES 模块版本

遇到的问题

(1). Node版本太低:确保你的 Node 版本至少为 18.0.0,并更新所有 Rollup 插件到最新版本 image.png (2). 以配置文件方式执行:npx rollup --config 或使用 Yarn: yarn rollup --config,这是用配置文件方式执行,需要定义配置文件(注意需要rollup配置,配置文件并定义配置文件,否则运行命令会报错。)。如果是命令行执行,则需要输入相关命令行参数, 配置文件方式执行,未定义配置文件,报错情况如下: image.png


参考

rollup.js中文文档