打包器又许多种,需要在适合的场景下使用适合的打包器,那么什么场景下适合使用 Rollup 呢?
如果你的代码库是基于 ES6 模块的,而且希望你写的代码能够被其他人直接使用(依赖库),你更需要的打包工具可能是 Rollup。
如果你的需求是需要代码拆分,或者你有很多静态资源需要处理,再或者你构建的项目需要引入很多 CommonJS 模块的依赖,那应该选择 webpack 。
rollup 是 node 命令,默认情况下,会将配置文件(rollup.config.js)当作 commonjs 模块来加载,如果要将配置文件作为 ES 模块来加载,需要进行以下处理:选其一即可
Rollup 默认只能使用 ES模块 编写代码,如果要使用 commonjs 模块需要使用 @rollup/plugin-commonjs 插件坐兼容处理。
TreeShaking 的作用是 按需打包。
无论是 ES模块 还是 commonjs模块,最终打包的 bundle 文件中只会包含 模块 中被使用的导出,没有被使用的导出不会被打包到 bundle 中。例如,
export 导出可以按需加载/打包,export default 导出会全部打包到 bundle 中。
// 使用了哪个函数,哪个函数会被打包到 bundle 中。只是被导入但是没有被使用的函数,也不会被打包
export function square ( x ) {
return x * x;
}
export function circle ( x ) {
return x * x;
}
// 会将导出的对象都打包到 bundle 中,除非,这个模块只是被导入了,但是根本没有使用这个对象。
export default {
square ( x ) {
return x * x;
},
circle ( x ) {
return x * x;
}
}
commonjs模块的 TreeShaking 和 ES模块类似。
// 按需加载,按需打包
module.exports.slice = (str) => { return str.slice(0, 3) }
module.exports.split = () => { return null; }
exports.slice = (str) => { return str.slice(0, 3) }
exports.split = () => { return null; }
// 会将导出的对象都打包到 bundle 中,除非,这个模块只是被导入了,但是根本没有使用这个对象。
module.exports = {
slice: (str) => { return str.slice(0, 3) },
split: (str) => { return null }
}
默认情况下,Rollup 只解析 相对模块。如果在你的项目中引入第三方依赖,例如像下面的 import 语句,不会导致 moment 被打包到你的包中——相反,它将是运行时需要的 外部依赖项。
import moment from 'moment';
rollup 编译代码时会提示警告信息:
moment (imported by src/xxx.tsx)
(!) Missing global variable names
Use output.globals to specify browser global variable names corresponding to external modules
如果这就是你想要的,你可以用 external 选项消除这个警告,这会让你的意图更加明确:
// rollup.config.js
export default {
entry: 'src/index.js',
dest: 'bundle.js',
format: 'cjs',
external: ['moment'] // <-- 消除这个警告
};
如果你确实想在打包后的代码中包含这个模块,需要告诉 Rollup 如何找到它。大多数情况下,你可以使用 @rollup/plugin-node-resolve。
有些模块,如 events 或 util,是内置在 Node.js 中的。如果你想要包含它们(例如,让你的包在浏览器中运行),你可能需要使用 rollup-plugin-polyfill-node。
通过 external 选项配置要提取的外部依赖。
当创建 iife 或 umd 格式的 bundle 时,你需要通过 output.globals 选项提供全局变量名,以替换掉外部引入。
export default {
input: 'src/index.js',
output: {
file: 'public/bundle.js',
name: 'myBundle',
format: 'umd',
globals: {
lodash: '_',
'./utils/math': 'util'
}
},
plugins: [commonjs()],
external: [
'lodash',
'./utils/math'
]
};
配置在 plugins 选项中。
export default {
input: 'src/TakePhoto/index.tsx',
output: {
file: 'dist/TakePhoto/index.js',
name: 'TakePhoto',
format: 'umd',
globals: {
react: 'React'
}
},
plugins: [
del({
// 要清空的目录
targets: 'dist/*',
// 在控制台输出删除的文件
verbose: true
})
],
};
@rollup/plugin-terser
const terser = require('@rollup/plugin-terser');
export default {
// 其他配置
plugins: [
terser()
],
};
const typescript = require( '@rollup/plugin-typescript');
export default {
// 其他配置
plugins: [
// 选项中的配置可以覆盖 ts.config.js 中的配置项
typescript({
"include": [
"src/TakePhoto/*",
"src/types.d.ts"
]
}),
],
};
@rollup/plugin-image
const image = require('@rollup/plugin-image');
export default {
// 其他配置
plugins: [
image()
],
};
npm i rollup-plugin-postcss postcss postcss-url autoprefixer -D
export default {
// 其他配置
plugins: [
postcss({
extensions: ['.css', '.scss'],
// 样式插入到 head 标签中
inject: true,
// 压缩样式
minimize: true,
// 配置 postPlugin
plugins: [
// 处理 css 中的 url,图片或字体
postCssUrl({
url: 'inline'
}),
// 添加前缀
autoprefixer()
],
}),
],
};
postCss 插件
export default {
// 其他配置
plugins: [
postcss({
// 其他配置...
// 配置 postPlugin
plugins: [
// 处理 css 中的 url,图片或字体
cssUrl({
limit: 10 * 1024,
imgOutput: 'dist/TakePhoto/img',
cssOutput: 'dist/TakePhoto'
}),
],
}),
],
};
注意:
如果使用此插件编译css,那么样式中的背景图片,不能直接使用 background 联合配置,需要分开书写,否则 url 后面的配置回去删除。例如:
// before
background: #0086ed url("./images/camera.svg") no-repeat center center;
// after
background: url("img/camera.svg");
解决方法:
background-color: #0086ed;
background-image: url("./images/camera.svg");
background-repeat: no-repeat;
backgound-position: center center;