一、什么是Rollup
Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。Rollup 对代码模块使用新的标准化格式,这些标准都包含在 JavaScript 的 ES6 版本中,而不是以前的特殊解决方案,如 CommonJS 和 AMD。ES6 模块可以使你自由、无缝地使用你最喜爱的 library 中那些最有用独立函数,而你的项目不必携带其他未使用的代码。ES6 模块最终还是要由浏览器原生实现,但当前 Rollup 可以使你提前体验。
Rollup中文官网
二、为什么选择Rollup
1、Tree-Shaking
tree shaking是rollup提出的,这也是rollup一个非常重要的feature,那什么是tree shaking,rollup的解释是在构建代码时,在使用ES6模块化的代码中,会对你的代码进行静态分析,只打包使用到的代码。这样的好处是减少代码的体积,该功能也在webpack 4得到了实现。
2、多种输出格式的支持
amd - AMD
cjs -CommonJS
es - ES6 modules
umd - UMD
system - SystemJS loader
3、兼容性
导入 CommonJS(Importing CommonJS)
Rollup 可以通过插件导入已存在的 CommonJS 模块。
发布 ES6 模块(Publishing ES6 Modules)
为了确保你的 ES6 模块可以直接与「运行在 CommonJS(例如 Node.js 和 webpack)中的工具(tool)」使用,你可以使用 Rollup 编译为 UMD 或 CommonJS 格式,然后在 package.json 文件的 main 属性中指向当前编译的版本。如果你的 package.json 也具有 module 字段,像 Rollup 和 webpack 2 这样的 ES6 感知工具(ES6-aware tools)将会直接导入 ES6 模块版本。
浏览器兼容性
可以通过配置es3的编译工具,将目标代码编译至es3,配合polyfill,对于有向下兼容IE8的用户提供了兼容服务。
输出代码非常纯净,没有任何多余代码,不像webpack打包后生成的文件会自动注入很多代码,导致目标文件代码非常ugly。
三、脚手架选择
Rollup:
适合写库(lib)、工具(sdk)以及小型应用,生成的目标代码更纯净。
Webpack:
更适合写中大型应用程序,生态更佳,第三方插件更丰富。
四、使用Rollup
通常项目中使用配置文件去使用Rollup,项目中我习惯将配置文件分成三份:rollup.base.conf.js、rollup.dev.conf.js、rollup.prod.conf.js。
rollup.base.conf.js
import json from 'rollup-plugin-json';
import resolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';
import commonjs from 'rollup-plugin-commonjs';
import es3 from 'rollup-plugin-es3';
import {eslint} from 'rollup-plugin-eslint';
import pkg from '../package.json';
export default {
input: pkg.src,
output: {
file: pkg.main,
format: 'umd',
name: 'EUtils',
sourcemap: true
},
watch: {
include: 'src/**'
},
plugins: [
resolve(),
commonjs(),
json(),
eslint({
include: 'src/**',
exclude: ['node_modules/**', 'dist/**'],
}),
babel({
babelrc: false,
presets: [['env', {modules: false, loose: true}]],
include: ['src/**', 'test/**'],
plugins: ['external-helpers'],
runtimeHelpers: true
}),
es3({
remove: ['defineProperty', 'freeze']
}),
],
};
rollup.dev.conf.js
import { merge } from 'lodash';
import rollupBaseConf from './rollup.base.conf';
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
const devConfig = {
plugins: [
serve({
open: true, // 是否打开浏览器
contentBase: './', // 入口html的文件位置
historyApiFallback: true, // Set to true to return index.html instead of 404
host: 'localhost',
port: 8888
}),
livereload(),
],
};
const config = merge(rollupBaseConf, devConfig);
export default config;
rollup.prod.conf.js
import baseConf from './rollup.base.conf';
import { merge } from 'lodash';
import { uglify } from 'rollup-plugin-uglify';
const prodConf = merge(baseConf, {
plugins: [
uglify({
compress: {
drop_console: true,
}
}),
]
});
export default prodConf;
本地启动项目:
package.json:
"scripts": {
"build": "npm run clean && npm run lib && rollup --config build/rollup.prod.conf.js",
"start": "npm run dev",
"clean": "rimraf dist/** lib/**",
"dev": "rollup --config build/rollup.dev.conf.js -w && livereload 'dist/'",
"test": "jest --config ./jest.conf.js --coverage"
},
此例是我用rollup来构建一个通用函数库所使用的配置,最终形成的.min.js文件非常纯净,同时可集成jest测试框架来测试编写的函数功能。
五、集成测试框架
jest是一个极易上手的测试框架,能测试很多应用场景,下面是我用来测试函数功能的配置文件:
const path = require('path');
module.exports = {
rootDir: path.resolve(__dirname, './'),
verbose: true,
moduleFileExtensions: ['js', 'json',],
moduleNameMapper: {'^@/(.*)$': '
/src/$1',}, transform: {'^.+\\.js$': '
/node_modules/babel-jest',}, testPathIgnorePatterns: ['
/test/e2e',], coverageDirectory: '
/test/coverage/', collectCoverageFrom: [
'src/**/*.js',
'!src/index.js',
'!src/position.js',
'!src/internal/**',
'!src/scrollTop.js',
'!**/node_modules/**',
'!src/*Cookie*.js',
'!src/getStylePrefix.js'
],
};
其中collectCoverageFrom是配置所要测试的文件,带“!”表示不覆盖该文件的测试。