如果您在使用webpack1.X,您就会知道其无法避免引入冗余模块代码,导出打包出来的bundle文件难免有点臃肿。
当然,您可以通过ES2015的解构赋值语法引入模块,可以让打包工具最终编译出来的代码尽可能最小化,但是如果您比较习惯用类似webpack做模块化打包的话,可能有点折腾。所以,今天和大家介绍一个新的前端模块化的打包工具Rollup,Rollup在编译打包模块过程中,通过Tree-shaking的方式,利用ES6模块能够静态分析语法树的特性,剔除各模块中最终未被引用到的方法,通过仅保留被调用到的代码块来减小bundle文件大小。它和webpack 2.X在一定程度上很相似,孰优孰劣,在这我们就不去讨论,这篇文章重点是向大家简单介绍一下Rollup。
使用
通过npm进行安装
npm install -g rollup
执行打包方式和webpack类似:
*******************************************************
将入口文件src/main.js打包输出-o/--output为rel/bundle.js
*******************************************************
rollup src/main.js -o rel/bundle.js
Rollup打包新增编译运行格式-f/--format参数,您通过指定参数可以编译出来的模块执行您想要的格式
*****************************************
commonjs
*****************************************
rollup src/main.js -o rel/bundle.js -f cjs
还有其他可选格式:
amd、es6、iife、umd等
来看看官方simple project,带我们入门
首先,创建例子入口文件
// src/main.js
import { cube } from './maths.js';
console.log( cube( 5 ) );
再搞个maths.js引入文件
// src/maths.js
export function square ( x ) {
return x * x;
}
export function cube ( x ) {
return x * x * x;
}
最终得到bundel.js内容如下:
'use strict';
function cube ( x ) {
// rewrite this as `square( x ) * x`
// and see what happens!
return x * x * x;
}
console.log( cube( 5 ) );
上面可以看出maths未调用过的square方法经过Tree-shaking的作用后并未在bundel.js里出现。
另外Tree-shaking 会抽取引用到的模块内容,将它们置于同一个作用域下,进而直接用变量名就可以访问各个模块的接口。而不像 webpack 这样每个模块外还要包一层函数定义,再通过合并进去的 define/require 相互调用。当然,这种方法需要 ES2015 的解构赋值语法来配合,多亏了它,Rollup 才能有效地对模块内容进行可靠的静态分析。
Using config files
和webpack一样,Rollup也支持通过config file 来灵活使用。我们在根目录下建个rollup.config.js文件:
export default {
entry: 'src/main.js',
format: 'cjs',
dest: 'rel/bundle.js'
};
在此目录下执行打包:
*****************************************
rollup -c /--config [config filename]
*****************************************
rollup -c
当然,它也是支持使用插件的,直接写到配置文件里plugins里即可:
import babel from 'rollup-plugin-babel';
export default {
entry: 'src/main.js',
format: 'cjs',
plugins: [ babel() ],
dest: 'rel/bundle.js'
};
执行npm安装rollup-plugin-babel
npm install rollup-plugin-babel
不过大家要注意的是,Rollup类似babel的预设不能像webpack可以直接写在配置文件里,必须通过.babelrc的configured文件来进行,此文件存放目录不规定一定在根目录下
//src/.babelrc
{
"presets": [
["latest", {
"es2015": {
"modules": false
}
}]
],
"plugins": ["external-helpers"]
}
并执行npm安装babel-preset-es2015-rollup
npm install babel-preset-es2015-rollup
这样就可以配合babel一起把es6的模块编译为es5的bundle进行使用。
为了方便跟gulp等工具协作,Rollup也支持被调用执行,比如:
//rollup.config.js
var rollup = require( 'rollup' );
var babel = require('rollup-plugin-babel');
rollup.rollup({
entry: 'src/main.js',
plugins: [ babel() ]
}).then( function ( bundle ) {
bundle.write({
format: 'umd',
moduleName: 'main', //umd或iife模式下,若入口文件含 export,必须加上该属性
dest: 'rel/bundle.js',
sourceMap: true //设置 source map,会自动生成一个 rel/bundle.js.map 关联到 rel/bundle.js 中。也可以设置为inline直接内联在 bundle 里而不是独立生成一个 map 文件
});
});
然后node执行
node rollup.config.js
注意 “rollup.rollup()”返回一个带着 bundle 作为 resolve 回调参数的 Promise 对象,我们常规直接使用语法糖 bundle.write 来打包输出文件:
bundle.write({
format: 'umd',
moduleName: 'main',
dest: 'rel/bundle.js'
});
//其等价于
var result = bundle.generate({
format: 'umd',
moduleName: 'main',
dest: 'rel/bundle.js',
});
fs.writeFileSync( 'rel/bundle.js', result.code );
Rollup简单的介绍就到这,Rollup的出现也有一段时间了,如果您对它感兴趣的话可以去了解和使用,前端这些年出现的利器不少,它之所以没红起来,我想有个很大的原因就是前端生出利器时间过短,人们没反应过来。所以,要当好一个前端就得加快学习的脚本,共勉!