What & Why
如果你将项目拆分成小的单独文件中,这样开发软件通常会很简单,因为这通常会消除无法预知的相互影响(remove unexpected interaction),以及显著降低了所要解决的问题的复杂度(complexity of the problem),并且可以在项目最初时,就简洁地编写小的项目(不一定是标准答案)。不幸的是,JavaScript 以往并没有将此功能作为语言的核心功能。 — From 官网,以及显著降低了所要解决的问题的复杂度(complexity of the problem),并且可以在项目最初时,就简洁地编写小的项目(不一定是标准答案)。不幸的是,JavaScript 以往并没有将此功能作为语言的核心功能。)
上面一句话其实阐述的是对于前端打包工具的必要性。因为JS以前没有支持模块化,但在工程开发的时候是一定需要模块化的,所以,这些零散的文件需要再被重新整理到一起,这就是打包工具做的事情。(尽管现在有了esm规范,但是毕竟还是有历史遗留问题,除了现代浏览器或者node之外的环境也用不了esm规范)
Rollup就是这样的工具,而且目的很纯粹。因为他适合做的事情相对于webpack来说是小而精。Rollup现在更广泛的应用在Library打包的领域。(webpack更专注于大型应用开发)
提到Rollup就还需要说到一个重要的特性,TreeShaking,Rollup可谓是最早的Tree Shaking概念提出者和实现者。
简单来说就是打包的时候,通过对代码静态分析,将那些没有使用到变量和函数“过滤”掉,使他们不要出
现到目标文件中。(Tree Shaking,这个词也是很形象,使劲摇这颗树,让那些没有关联关系的掉下来)
快速上手
通常在项目里面,配置文件是较为常用的使用方式,不过可以从命令行了解起来。
使用命令行
安装rollup:全局 -g 安装或者用npx rollup
打包命令:
rollup --input index.js --file dist.js --format umd
上面的命令解释如下:
—format umd 也可以选择 cjs、es、iife等不同的目标文件规范(一共支持6种 amd、es、iife、umd、cjs、system)
—input 指定就是入口文件
—file 就是指定目标文件
当然还有其他的参数:
- -i 等同于 —input就是输入文件
- —file 是输出文件
- —dir 直接建一个文件夹 用于多文件输入
- —format 可以选择 cjs、es、iife等不同的目标文件规范
- —watch 监听模式
- —environment 注入环境变量 (比如—environment TEST:234 ,那么通过process.env.TEST 就可以取到234)
- —plugin 使用插件
- —name 使用umd方式的时候如果有输出则需要指明name,这个name就是最终window.name = 你输出的
- -c 指定rollup.config.js
以上就是比较常用的,了解全部参数参考官方文档。
使用配置文件
Rollup的配置文件很方便,通过-c 指定配置文件,比如 rollup -c cfg.js,或者直接rollup -c,这时候rollup会加载默认的配置文件:rollup.config.js。
rollup.config.js是一个ES6模块,它对外暴露一个对象,这个对象包含了一些Rollup需要的一些选项,比如:
// rollup.config.js
export default {
input: 'src/main.js',
output: {
file: 'bundle.js',
format: 'cjs'
}
};
上面这个文件可以说是最简单的了,声明了入口src/main.js,声明了目标文件bundle.js和目标文件模块规范是cjs,即commonjs。
这些是全部配置了, 具体含义参考这里:
// rollup.config.js
export default {
// 核心选项
input, // 必须
external,
plugins,
// 额外选项
onwarn,
// danger zone
acorn,
context,
moduleContext,
legacy
output: { // 必须 (如果要输出多个,可以是一个数组)
// 核心选项
file, // 必须
format, // 必须
name,
globals,
// 额外选项
paths,
banner,
footer,
intro,
outro,
sourcemap,
sourcemapFile,
interop,
// 高危选项
exports,
amd,
indent
strict
},
};
常见插件
resolve与commonjs
指的是:@rollup/plugin-node-resolve和@rollup/plugin-commonjs,为什么需要resolve + commonjs呢?
rollup默认不知道如何读取node_modules下面的依赖,这两个东西是为了解决这个问题,所以,通常用来把第三方的依赖打入包中。(比如react,如果没有这两个react不会打进最终的包,但是如果有了就能被打进了,这当然是不一定必要,有时候我们还专门不需要react)
具体的resolve用来加载node_modules,commonjs用来加载那些在node_modules中的cjs规范的(rollup默认期望是esm)
import resolve from '@rollup/plugin-node-resolve' // 打第三方包 打一起
import commonjs from '@rollup/plugin-commonjs' // 第三方库有时候是cjs的
具体使用是有顺序要求的:
export default {
input: entry,
external: ['react'], // 需要不包含进入的
plugins: [resolve(), commonjs())], // rollup的插件按照顺序执行
output: [
{
file: 'dist/main.umd.js',
format: 'umd',
name: 'Index'
},
{
file: 'dist/main.es.js',
format: 'es',
}
]
}
上门这段代码,其实不希望react被打包进来,但是又有其他的包需要resovle,所以我们许呀配置external: [‘react’],这样打包文件中就不包括react了。
typescript
要支持typescript,这三个都需要安装@rollup/plugin-typescript、typescript、tslib:
yarn add @rollup/plugin-typescript typescript tslib -D
@rollup/plugin-typescript也会加载根目录下的typescript.config.json,不过直接npx typescript —init直接生成typescript.config.json也不错。
PS:还有一个非官方的插件rollup-plugin-typescript,这个插件比官方的多了一些功能,会输出类型校验的错误。
eslint
需要安装@rollup/plugin-eslint、eslint:
yarn add @rollup/plugin-eslint eslint
此外可以安装下预设规范:
// 安装一些预设规范
yarn add eslint-config-standard eslint-plugin-import eslint-plugin-promise eslint-plugin-node -D
这样可以加载.eslintrc.js的规则
module.exports = {
extends: 'standard',
globals: {
postMessage: true
},
rules: {
'space-before-function-paren': 'off'
}
}
image
这个插件会把import的图片资源作为base64打包到目标代码中
yarn add @rollup/plugin-image
strip
这个插件的目的是打包之后的文件,移除掉最外层的console、debugger等….
yarn add @rollup/plugin-strip
postcss
安装rullup-plugin-postcss
yarn add rullup-plugin-postcss -D
安装之后,比如这样:
import './main.css'
打包生成的文件js,其原理就是类似style-loader的功能,可以把import的css用js代码作为style插入。
terser
terser就是压缩代码的,rollup对应的就是rollup-plugin-terser
yarn add rollup-plugin-terser -D
这个插件可以作为plugin,也可以作为output的plugin:
export default {
input: entry,
plugins: [resolve(), commonjs(), /* terser() */ ], // terser可以出现在这
output: [
{
file: 'dist/main.es.js',
format: 'es',
plugins: [terser()] // 也可以作为输出阶段的插件
}
]
}