跳至内容

教程

创建您的第一个包

在我们开始之前,您需要安装 Node.js,以便您可以使用 NPM。您还需要了解如何在您的机器上访问 命令行

使用 Rollup 的最简单方法是通过命令行界面 (CLI)。现在,我们将全局安装它(稍后我们将学习如何将其本地安装到您的项目中,以便您的构建过程可移植,但现在不用担心)。在命令行中输入以下内容

shell
npm install rollup --global
# or `npm i rollup -g` for short

现在您可以运行 rollup 命令。试试看!

shell
rollup

由于没有传递参数,Rollup 会打印使用说明。这与运行 rollup --helprollup -h 相同。

让我们创建一个简单的项目

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

首先,我们需要一个入口点。将此粘贴到一个名为 src/main.js 的新文件中

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

然后,让我们创建我们的入口点导入的 foo.js 模块

js
// src/foo.js
export default 'hello world!';

现在我们准备创建一个包

shell
rollup src/main.js -f cjs

-f 选项(--format 的简写)指定我们要创建的包类型 - 在这种情况下,是 CommonJS(它将在 Node.js 中运行)。因为我们没有指定输出文件,所以它将直接打印到 stdout

js
'use strict';

const foo = 'hello world!';

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

module.exports = main;

您可以将包保存为文件,如下所示

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

(您也可以执行 rollup src/main.js -f cjs > bundle.js,但正如我们稍后将看到的那样,如果您正在生成源映射,这将不太灵活。)

尝试运行代码

node
> var myBundle = require('./bundle.js');
> myBundle();
'hello world!'

恭喜!您已使用 Rollup 创建了第一个包。

使用配置文件

到目前为止,一切都很好,但是当我们开始添加更多选项时,在命令行中输入命令会变得有点麻烦。

为了避免重复输入,我们可以创建一个配置文件,其中包含我们需要的全部选项。配置文件是用 JavaScript 编写的,比原始 CLI 更灵活。

在项目根目录中创建一个名为 rollup.config.mjs 的文件,并添加以下代码

js
// rollup.config.mjs
export default {
	input: 'src/main.js',
	output: {
		file: 'bundle.js',
		format: 'cjs'
	}
};

(请注意,您可以使用 CJS 模块,因此 module.exports = {/* config */}

要使用配置文件,我们使用 --config-c 标志

shell
rm bundle.js # so we can check the command works!
rollup -c

您可以使用等效的命令行选项覆盖配置文件中的任何选项

shell
rollup -c -o bundle-2.js # `-o` is equivalent to `--file` (formerly "output")

注意:Rollup 本身会处理配置文件,这就是为什么我们可以使用 export default 语法的原因 - 代码没有使用 Babel 或类似的东西进行转译,因此您只能使用您正在运行的 Node.js 版本支持的 ES2015 功能。

如果您愿意,可以指定与默认 rollup.config.mjs 不同的配置文件

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

在本地安装 Rollup

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

要使用 NPM 在本地安装 Rollup

shell
npm install rollup --save-dev

或使用 Yarn

shell
yarn -D add rollup

安装后,可以在项目的根目录中运行 Rollup

shell
npx rollup --config

或使用 Yarn

shell
yarn rollup --config

安装后,通常的做法是在 package.json 中添加一个构建脚本,为所有贡献者提供一个方便的命令。例如

json
{
	"scripts": {
		"build": "rollup --config"
	}
}

注意:在本地安装后,NPM 和 Yarn 都将解析依赖项的 bin 文件,并在从包脚本调用时执行 Rollup。

使用插件

到目前为止,我们已经从入口点和通过相对路径导入的模块创建了一个简单的包。在构建更复杂的包时,您通常需要更多灵活性 - 导入使用 NPM 安装的模块、使用 Babel 编译代码、使用 JSON 文件等等。

为此,我们使用插件,它们会在捆绑过程的关键点更改 Rollup 的行为。在 Rollup Awesome List 上维护着很棒的插件列表。

在本教程中,我们将使用 @rollup/plugin-json,它允许 Rollup 从 JSON 文件导入数据。

在项目根目录中创建一个名为 package.json 的文件,并添加以下内容

json
{
	"name": "rollup-tutorial",
	"version": "1.0.0",
	"scripts": {
		"build": "rollup -c"
	}
}

将 @rollup/plugin-json 作为开发依赖项安装

shell
npm install --save-dev @rollup/plugin-json

(我们使用 --save-dev 而不是 --save,因为我们的代码在运行时实际上并不依赖于插件 - 只有在构建包时才依赖。)

更新您的 src/main.js 文件,使其从您的 package.json 而不是 src/foo.js 导入

js
// src/main.js
import { version } from '../package.json';

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

编辑您的 rollup.config.mjs 文件以包含 JSON 插件

js
// rollup.config.mjs
import json from '@rollup/plugin-json';

export default {
	input: 'src/main.js',
	output: {
		file: 'bundle.js',
		format: 'cjs'
	},
	plugins: [json()]
};

使用 npm run build 运行 Rollup。结果应该如下所示

js
'use strict';

var version = '1.0.0';

function main() {
	console.log('version ' + version);
}

module.exports = main;

注意:只有我们实际需要的数据才会被导入 - namedevDependencies 以及 package.json 的其他部分将被忽略。这就是树摇的作用。

使用输出插件

某些插件也可以专门应用于某些输出。有关输出特定插件可以执行的操作的技术细节,请参阅 插件钩子。简而言之,这些插件只能在 Rollup 的主要分析完成后修改代码。如果将不兼容的插件用作输出特定插件,Rollup 会发出警告。一个可能的用例是缩小要在浏览器中使用的包。

让我们扩展前面的示例,以提供一个缩小的构建以及非缩小的构建。为此,我们安装 @rollup/plugin-terser

shell
npm install --save-dev @rollup/plugin-terser

编辑您的 rollup.config.mjs 文件以添加第二个缩小的输出。作为格式,我们选择 iife。这种格式包装了代码,使其可以通过浏览器中的 script 标签使用,同时避免与其他代码发生不必要的交互。由于我们有一个导出,我们需要提供一个全局变量的名称,该变量将由我们的包创建,以便其他代码可以通过此变量访问我们的导出。

js
// 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()]
};

除了 bundle.js 之外,Rollup 现在还会创建一个名为 bundle.min.js 的第二个文件

js
var version = (function () {
	'use strict';
	var n = '1.0.0';
	return function () {
		console.log('version ' + n);
	};
})();

代码拆分

对于代码拆分,在某些情况下 Rollup 会自动将代码拆分为块,例如动态加载或多个入口点,并且有一种方法可以通过 output.manualChunks 选项明确告诉 Rollup 将哪些模块拆分为单独的块。

要使用代码拆分功能来实现延迟动态加载(其中某些导入的模块仅在执行函数后加载),我们回到原始示例并修改 src/main.js 以动态加载 src/foo.js 而不是静态加载

js
// src/main.js
export default function () {
	import('./foo.js').then(({ default: foo }) => console.log(foo));
}

Rollup 将使用动态导入来创建一个单独的块,该块仅在需要时加载。为了让 Rollup 知道将第二个块放在哪里,我们没有传递 --file 选项,而是使用 --dir 选项设置一个输出文件夹

shell
rollup src/main.js -f cjs -d dist

这将创建一个包含两个文件的文件夹 dist,分别是 main.jschunk-[hash].js,其中 [hash] 是一个基于内容的哈希字符串。您可以通过指定 output.chunkFileNamesoutput.entryFileNames 选项来提供您自己的命名模式。

您仍然可以像以前一样运行您的代码,并获得相同的输出,尽管速度会稍微慢一些,因为加载和解析 ./foo.js 只有在我们第一次调用导出的函数时才会开始。

shell
node -e "require('./dist/main.js')()"

如果我们不使用 --dir 选项,Rollup 将再次将块打印到 stdout,并添加注释以突出显示块边界

js
//→ main.js:
'use strict';

function main() {
	Promise.resolve(require('./chunk-b8774ea3.js')).then(({ default: foo }) =>
		console.log(foo)
	);
}

module.exports = main;

//→ chunk-b8774ea3.js:
('use strict');

var foo = 'hello world!';

exports.default = foo;

这在您只想在使用时加载和解析昂贵的特性时很有用。

代码拆分的另一个用途是能够指定多个共享某些依赖项的入口点。我们再次扩展我们的示例,添加第二个入口点 src/main2.js,它像我们在原始示例中所做的那样静态导入 src/foo.js

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

如果我们将两个入口点都提供给 rollup,则会创建三个块

shell
rollup src/main.js src/main2.js -f cjs

将输出

js
//→ main.js:
'use strict';

function main() {
	Promise.resolve(require('./chunk-b8774ea3.js')).then(({ default: foo }) =>
		console.log(foo)
	);
}

module.exports = main;

//→ main2.js:
('use strict');

var foo_js = require('./chunk-b8774ea3.js');

function main2() {
	console.log(foo_js.default);
}

module.exports = main2;

//→ chunk-b8774ea3.js:
('use strict');

var foo = 'hello world!';

exports.default = foo;

请注意,两个入口点如何导入相同的共享块。Rollup 永远不会重复代码,而是创建额外的块,以仅加载必要的最小代码。同样,传递 --dir 选项会将文件写入磁盘。

您可以为浏览器构建相同的代码,通过原生 ES 模块、AMD 加载器或 SystemJS。

例如,对于原生模块,使用 -f es

shell
rollup src/main.js src/main2.js -f es -d dist
html
<!doctype html>
<script type="module">
	import main2 from './dist/main2.js';
	main2();
</script>

或者,对于 SystemJS,使用 -f system

shell
rollup src/main.js src/main2.js -f system -d dist

通过以下方式安装 SystemJS

shell
npm install --save-dev systemjs

然后根据需要在 HTML 页面中加载一个或两个入口点

html
<!doctype html>
<script src="node_modules/systemjs/dist/s.min.js"></script>
<script>
	System.import('./dist/main2.js').then(({ default: main }) => main());
</script>

有关如何设置使用原生 ES 模块的 Web 应用程序(在支持它们的浏览器上)以及在必要时回退到 SystemJS 的示例,请参阅 rollup-starter-code-splitting

根据 MIT 许可发布。