随着前端的复杂性,工程化、组件化、模块化已经成为项目的必需品,而这些目标的实现都需要工具来帮助开发者完成,目前最流程的几大构建工具中,常用的有Webpack和Rollup
Rollup被成为下一代模块打包器,可对es6模块编写的程序友好地打包。开发者可以将项目拆分成多个小文件,从而降低代码复杂度,消除不可预知的相互影响,减少出错率。而Roolup可以将多个小文件打包输出为一个最终文件。
Rollup
一般用于库程序或部分应用程序。因为Rollup还不支持一些特定的高级功能,比如:code-splitting,dynamic imports,此时可以使用Webpack。
1. 特性
ES6
Rollup
可以直接使用ES6的语法,通过import``export
管理模块,替代了原来Commonjs和AMD的require方式
Tree-shaking
对代码静态分析,仅打包输出实际用到的代码。这样可以大大降低输出文件的大小。
// foo.js
export function getName() { console.log('lisa') }
export function getSex() { console.log('female') }
// main.js
import { getName } from './foo'
function main() {
getName()
}
以上cjs打包输出则只输出引用到的函数
'use strict';
function getName() {
console.log('Lisa');
}
function main () {
getName();
}
module.exports = main;
多格式
Roolup
可以提供多种输出格式,方便兼容Commonjs,ES6模块等。可到官网REPL查看编译后的各种输出格式的区别
/* DEFAULT EXPORTS
Default exports from the 'entry module' are
exported from the bundle */
import answer from './answer.js';
export default function () {
console.log( 'the answer is ' + answer );
// answer.js
export default 42;
}
-
cjs
: nodejs格式
'use strict';
var answer = 42;
/* DEFAULT EXPORTS
Default exports from the 'entry module' are
exported from the bundle */
function main () {
console.log( 'the answer is ' + answer );
}
module.exports = main;
-
esm
: ES6格式
var answer = 42;
/* DEFAULT EXPORTS
Default exports from the 'entry module' are
exported from the bundle */
function main () {
console.log( 'the answer is ' + answer );
}
export default main;
-
iife
: 原生立即执行函数
var myBundle = (function () {
'use strict';
var answer = 42;
/* DEFAULT EXPORTS
Default exports from the 'entry module' are
exported from the bundle */
function main () {
console.log( 'the answer is ' + answer );
}
return main;
}());
-
umd
: 多环境兼容
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global.myBundle = factory());
}(this, (function () { 'use strict';
var answer = 42;
/* DEFAULT EXPORTS
Default exports from the 'entry module' are
exported from the bundle */
function main () {
console.log( 'the answer is ' + answer );
}
return main;
})));
2. 构建脚本
2.1 构建
安装
npm install rollup --global # or `npm i rollup -g` for short
创建脚本
// main.js
import foo from './foo.js';
export default function () {
console.log(foo);
}
// foo.js
export default 'hello world'
构建
rollup main.js -f cjs -o bundle.js
输出文件
'use strict';
var foo = 'hello world!';
function main () {
console.log(foo);
}
module.exports = main;
2.2 命令行参数
详见官网命令行参数
-i, --input 要打包的文件(必须)
-o, --output.file 输出的文件 (如果没有这个参数,则直接输出到控制台)
-f, --output.format [es] 输出的文件类型 (amd, cjs, es, iife, umd)
-e, --external 将模块ID的逗号分隔列表排除
-g, --globals 以`module ID:Global` 键值对的形式,用逗号分隔开
任何定义在这里模块ID定义添加到外部依赖
-h, --help 打印帮助文档
-n, --name 生成UMD模块的名字
-m, --sourcemap 生成 sourcemap (`-m inline` for inline map)
-v,--version 打印安装的Rollup版本号
-w,--watchc 监听源文件。若有改动,则重新打包
--amd.id AMD模块的ID,默认是个匿名函数
--amd.define 使用Function来代替`define`
--no-strict 在生成的包中省略`"use strict";`
--no-conflict 对于UMD模块来说,给全局变量生成一个无冲突的方法
--intro 在打包好的文件的块的内部(wrapper内部)的最顶部插入一段内容
--outro 在打包好的文件的块的内部(wrapper内部)的最底部插入一段内容
--banner 在打包好的文件的块的外部(wrapper外部)的最顶部插入一段内容
--footer 在打包好的文件的块的外部(wrapper外部)的最底部插入一段内容
--interop 包含公共的模块(这个选项是默认添加的)
--slient 不要将警告打印到控制台
3. 配置文件及参数
实际开发更多使用配置文件。配置的核心功能:input
,output
, plugins
, 分别指定了 输入、输出、处理各类文件的插件
3.1 配置文件
创建rollup.config.js
文件,配置打包参数
export default {
input: "main.js",
output: {
file: 'bundle.js',
format: 'cjs'
}
}
输出多个文件格式
export default {
input: "main.js",
output: [{
file: 'dist/bundle.js',
format: 'cjs'
}, {
file: 'dist/umd.js',
format: 'umd',
name: 'myBundleName' // 用于输出时将函数定义绑定到该全局变量上,参见下面输出文件内容
}]
}
打包
rollup -c
输出文件内容
// bundle.js
'use strict';
var foo = 'hello world!';
function main () {
console.log(foo);
}
module.exports = main;
// umd.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global.myBundleName = factory());
}(this, (function () { 'use strict';
var foo = 'hello world!';
function main () {
console.log(foo);
}
return main;
})));
3.2 配置参数
具体说明见https://www.rollupjs.com/guide/big-list-of-options/
// rollup.config.js
export default {
// 核心选项
input, // 必须
external,
plugins,
// 额外选项
onwarn,
// danger zone
acorn,
context,
moduleContext,
legacy
output: { // 必须 (如果要输出多个,可以是一个数组)
// 核心选项
file, // 必须
format, // 必须
name, // UMD格式时必须
globals,
// 额外选项
paths,
banner,
footer,
intro,
outro,
sourcemap,
sourcemapFile,
interop,
// 高危选项
exports,
amd,
indent
strict
},
};
4. 插件
一些非JS
文件或高级JS
处理需要插件来扩展打包功能, 如:JSON文件,Babel编译、alias设置等。可用插件列表见这里
安装插件
npm install --save-dev rollup-plugin-json
代码
import { version } from '../package.json'
export default function() {
console.log('version' + version)
}
配置文件
// rollup.config.js
import json from 'rollup-plugin-json';
export default {
input: 'src/main.js',
output: {
file: 'bundle.js',
format: 'cjs'
},
plugins: [ json() ]
};
·rollup -c·后输出
'use strict';
var version = "1.0.0";
var main = function () {
console.log('version ' + version);
};
module.exports = main;
通过tree-shaking,仅输出引入的 version字段
Rollup API
Rollup
提供了JavaScript API,可以在Nodejs中使用,用于扩展Rollpup
-
rollup.rollup()
用于在Nodejs中扩展或定制打包流程
输入参数: input options
返回类型:Promise对象,解析一个bundle
对象,此对象包含一些属性和方法(generate()
,write()
),见如下示例
const rollup = require('rollup');
// see below for details on the options
const inputOptions = {...};
const outputOptions = {...};
async function build() {
// create a bundle
const bundle = await rollup.rollup(inputOptions);
console.log(bundle.imports); // an array of external dependencies
console.log(bundle.exports); // an array of names exported by the entry point
console.log(bundle.modules); // an array of module objects
// generate code and a sourcemap
const { code, map } = await bundle.generate(outputOptions);
// or write the bundle to disk
await bundle.write(outputOptions);
}
build();
-
rollup.watch()
监控文件的改变,重构文件。一般用于Nodejs定制开发模式下启动项目,和express
结合相当于实现了web-dev-server
const rollup = require('rollup');
const watchOptions = {...};
const watcher = rollup.watch(watchOptions);
watcher.on('event', event => {
// event.code 会是下面其中一个:
// START — 监听器正在启动(重启)
// BUNDLE_START — 构建单个文件束
// BUNDLE_END — 完成文件束构建
// END — 完成所有文件束构建
// ERROR — 构建时遇到错误
// FATAL — 遇到无可修复的错误
});
// 停止监听
watcher.close();
参考文章