Rollup快速手册

Rollup快速手册

【🚧 施工中】

[ ] 相关插件案例

介绍

常见词汇

捆绑包(bundle)

是指将多个源代码文件或模块组合成一个单独的文件或一组文件的过程

  • 减小文件数量,更有效在浏览器或者其他环境中加载和执行
  • 减少网络请求

用于部署在生产环境,一般会经过压缩和混淆

rollup 概念

  1. 向未来兼容
  2. 除屑优化(Tree-shaking)

向未来兼容

虽然ES6新特性在现代浏览器中已经稳定,但在 Nodejs 中还未完全落地

Rollup 的作用就是可以使用新的特性,然后打包成CommonJSAMD等格式,即使以后这些特性在 Nodejs 中完整支持,现在的代码也不需要改动(向未来兼容)

除屑优化

静态分析导入的代码,然后去除没有使用的代码,减少打包后的体积

📄 原始文件

1
const utils = require('./utils');`,

但使用的时候只用到utils中的ajax方法,打包出来会是:

📄 打包结果

1
import { ajax } from "./utils";

安装

全局安装

1
npm install rollup --global

本地安装

1
npm install rollup --save-dev

package.json中的scripts节点

1
2
3
4
5
{
"scripts": {
"build": "rollup --config"
}
}

基本使用

命令行

1
2
3
4
5
// src/main.js
import foo from "./foo.js";
export default function () {
console.log(foo);
}
1
2
// src/foo.js
export default "hello world!";
1
rollup src/main.js -f cjs
  • -f全称--format,指定为CommonJS
  • 没有指定输出文件,默认以stdout输出

得到输出内容

1
2
3
4
5
6
7
8
9
"use strict";

const foo = "hello world!";

const main = function () {
console.log(foo);
};

module.exports = main;

使用-o指定输出文件

1
rollup src/main.js -o bundle.js -f cjs

配置文件

1
2
3
4
5
6
7
8
9
10
11
// rollup.config.mjs
import xxplugin from "xxplugin";

export default {
input: "src/main.js",
output: {
file: "bundle.js", // 还可以使用 dir
format: "cjs",
},
plugins: [xxplugin()],
};
  • 如果输出一个以上的文件,需要使用output.dir

CJS的话,使用module.exports = {/* config */}

使用-c--config)指定配置文件

1
rollup -c
  • 会自动读取rollup.config.jsrollup.config.mjs,如果没有,会报错

可以在命令行随便覆盖配置文件的配置

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

🎇 一般会使用defindConfig函数,这样会有代码提示

1
2
3
4
5
6
// rollup.config.js
import { defineConfig } from "rollup";

export default defineConfig({
/* 你的配置 */
});

mjs 和 cjs

默认就是cjs,即使是.js文件。如果要使用mjs,需要在package.json中配置:

1
2
3
{
"type": "module"
}
  • 使用cjs的话,__dirname可用

TypeScript

@rollup/plugin-typescript插件可以让 Rollup 支持 TypeScript

  • 配置文件.ts
  • tsconfig.json中的include字段包含配置文件

TypeScript 中支持使用RollupOptions类型

1
2
3
4
5
6
7
// rollup.config.ts
import type { RollupOptions } from "rollup";

const config: RollupOptions = {
/* 你的配置 */
};
export default config;

注意事项

import.meta.url的路径是当前文件的路径,而不是process.cwd()的路径

路径使用

在 CommonJS 中,经常会用到__dirname,但是在 Rollup 原生 ES 模块中,是没有这个的,推荐使用import.meta.url来获取

1
2
3
4
5
6
7
8
// rollup.config.js
import { fileURLToPath } from 'node:url'

export default {
...,
// 为 <currentdir>/src/some-file.js 生成绝对路径
external: [fileURLToPath(new URL('src/some-file.js', import.meta.url))]
};

导入 pakage.json

例如自动将依赖项标记为external

node 17.5+中,可使用导入断言

1
2
3
4
5
6
7
import pkg from "./package.json" assert { type: "json" };

export default {
// Mark package dependencies as "external". Rest of configuration
// omitted.
external: Object.keys(pkg.dependencies),
};

在旧版node中,可以使用@rollup/plugin-json。或者使用 node 提供的createRequire

1
2
3
4
5
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
const pkg = require("./package.json");

// ...

或者直接使用fs模块读取文件内容

使用插件

🌎 Awesome Rollup

导入现有的 CommonJS 模块

1
npm install @rollup/plugin-commonjs --save-dev
  • 需要 node14+

从 JSON 文件中导入数据

1
npm install @rollup/plugin-json --save-dev
1
2
3
4
5
6
// src/main.js
import { version } from "../package.json";

export default function () {
console.log("version " + version);
}

输出插件

  • 等 Rollup 主要分析完了之后,再对代码进行别的操作,比如压缩加密之类的
1
npm install @rollup/plugin-terser --save-dev

👉 对于不同的输出格式,可以使用不同的插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// rollup.config.mjs
import json from "@rollup/plugin-json";
import terser from "@rollup/plugin-terser";

export default {
input: "src/main.js",
output: [
{
file: "bundle.js",
format: "cjs",
},
{
file: "bundle.min.js",
format: "iife",
name: "version",
plugins: [terser()],
},
],
plugins: [json()],
};

iife格式是将变量放到一个自动执行的函数中,这样就不会污染全局变量了

1
2
3
4
5
6
7
var version = (function () {
"use strict";
var n = "1.0.0";
return function () {
console.log("version " + n);
};
})();

配置选项

external

类型:(string | RegExp)[]| RegExp| string| (id: string, parentId: string, isResolved: boolean) => boolean

需要排除在打包之外的模块

  • 这些模块不会出现在打包后的代码中
  • rollup 会生成一个requireimport语句,让运行时去加载这些模块,以避免不必要的依赖项重复打包。
  • 部署到生产环境时,需要确保external指定的这些模块已经存在

匹配方式:

  1. 外部依赖名称

如果将import dependency.js标记为外部依赖,那么就传递dependency.jsimport "dependency"的话,传递dependency

  1. 解析过的模块 ID(疑问)

解析过的模块 ID,例如文件的绝对路径,或者node_modules中的模块

如果通过正则表达式/node_modules/匹配

  1. 自定义函数

三个参数可使用:(id, parent, isResolved) => boolean

  • id: 模块的 ID
  • parent: 引入这个模块的模块 ID
  • isResolved: 模块是否已经被插件解析,比如用@rollup/plugin-node-resolve插件解析过了
1
2
3
4
5
6
7
8
// rollup.config.js
export default {
external: (id) => {
// 排除所有以 'react' 开头的模块
return id.startsWith("react");
},
// 其他配置选项...
};

input

类型:字符串、字符串数组、{[entryName]: string}

打包的入口,例如main.tsindex.js

如果传过来的是一个数组,或者是上面的第三个类型,打包的产物也是分开的,除非输出的时候指定了output.file。那输出的文件名会跟随output.entryFileNames

output.file 和 output.dir

类型:字符串

output.file指定输出的文件,是一个具体文件;如果需要输出多个文件,需要使用output.dir

案例

打包 TypeScript

需要提前安装的有typescripttslib

1
npm install @rollup/plugin-typescript --save-dev

插件默认使用tsconfig.json中的配置,也可以在配置文件中指定

1
2
3
4
5
6
7
8
9
10
11
12
13
/// ...
export default {
input: "./main.ts",
output: {
dir: "output",
format: "cjs",
},
plugins: [
typescript({
compilerOptions: { lib: ["es5", "es6", "dom"], target: "es5" },
}),
],
};

其他配置错误根据报错提示修改就好了

作者

dsjerry

发布于

2023-09-03

更新于

2023-10-01

许可协议

评论