rollup是一个js打包器,用来将很细碎的js编译打包成大的复杂的东西,像是一个库或者一个应用。其使用了ES6自带的新标准来格式化和打包js代码,而不是原先的Commonjs或者AMD这类解决方案。ES6模块可以使你轻松的无缝的组合你所喜欢库中的独立函数(静态函数)。这使得最后可以实现本地化,rollup现在实现了这些。java
使用npm install --global rollup
命令下载安装。rollup既能够经过一个配置文件使用命令行接口来调用,也能够他本身的Javascript API
使用。运行rollup --help
查看可用的命令和参数。starter project template
有一些经常使用设置的说明,若是须要更详细的说明,点击user guide
。node
这些名设定你的应用的入口是main.js
,而且但愿这些导入最后打包成一个bundle.js
命名的文件。webpack
浏览器环境git
# compile to a <script> containing a self-executing function # 编译到一个<script>元素包含的独立的函数。 $ rollup main.js --format iife --output bundle.js
Node.js环境es6
# compile to a CommonJS module # 变异成一个CommonJS标准的模块 $ rollup main.js --format cjs --output bundle.js
浏览器和node.js兼容的环境github
# UMD format requires a bundle name $ rollup main.js --format umd --name "myBundle" --output bundle.js
把项目分红各个小的部分来开发软件一般活容易些。由于常常须要去掉代码不指望的行为,也可以很大程度上下降解决问题的复杂程度,并且能够只在项目的第一个位置写一些小的项目而不是 isn't necessarily the answer
。不幸的是,JavaScript自己的语言设计没有这类功能。web
为了可以实现ES6模块功能,rollup会静态地分析你所引入的模块,而后去掉没有真正用到的部分。这会帮助你至引入那些须要的东西,而且减小项目的体积。ajax
例如,若是使用CommonJS.整个的工具和库都会被导入。typescript
// import the entire utils object with CommonJS // 使用CommonJS整个的导入utils var utils = require( 'utils' ); var query = 'rollup'; // use the ajax method of the utils object // 仅使用utils中的ajax方法 utils.ajax( 'https://api.example.com?search=' + query ).then( handleResponse );
可是若是使用ES6模块系统。替代整个引入utils模块,而是仅仅引入咱们所须要的ajax
函数。npm
// import the ajax function with an ES6 import statement //使用es6语句引入ajax函数 import { ajax } from 'utils'; var query = 'rollup'; // call the ajax function // 调用ajax函数 ajax( 'https://api.example.com?search=' + query ).then( handleResponse );
由于rollup只包含最低所需,所以它打包的应用体积更小,更快速,而且使得应用和库之间解耦更松散。
由于这种方法是创建在import
和export
语句上,所以其效率极高,运行时自动缩减体积,探测打包文件中不须要的变量。
rollup 可以经过插件导入CommondJS模块。
为了保证你的ES6模块可以立刻被CommonJS的工具使用,例如在Node或者webpack中,你可使用rollup来转化成UMD或者CommonJS格式风格。而后指定编译的版本在一个有mian
属性的package.json
文件中。若是你的package.json文件也有module
域(属性),es6敏感的工具,如rollup以及webpack2将会直接导入ES6模块版本。、
step-by-step tutorial video series, with accompanying written walkthrough
miscellaneous issues in thewiki
.
开始以前,你的电脑应该已经安装了node.js,所以你可以使用npm,此外你也须要知道怎么使用命令行工具。
使用rollup最简单的方法就是经过命令行接口。如今咱们要全局安装rollup,在命令行输入以下命令。(稍后咱们将学习如何本地安装到你的项目中,那么你的打包将更加爱便捷,暂时先不要管这么多)。
npm install rollup --global # or `npm i rollup -g` for short
如今你可使用rollup
,命令了。
由于没有传递参数,因此rollup只是打印出使用说明。这根rollup --help
或者rollup -h
的结果是同样的。
如今,来建立一个简单的项目。
mkdir -p my-rollup-project/src cd my-rollup-project
首先,咱们须要一个入口点entry point
,粘贴下面的代码到main.js
文件中。
// src/main.js import foo from './foo.js'; export default function () { console.log(foo); }
而后在建立一个foo.js
文件,就是咱们导入点导入的文件。
// src/foo.js export default 'hello world!';
如今咱们来准备生成一个bundle。
rolup src/main.js --format cjs
--format
选项制定咱们要打包成什么格式。在这个例子中是CommonJS(可以在Node.js运行)。由于咱们没有制定输出的文件,所以将会打印到命令行。(标准输出stdout)。
'use strict'; var foo = 'hello world!'; var main = function () { console.log(foo); }; module.exports = main;
你可使用以下方法保存编译出来的bundle。
rollup src/main.js --format cjs --output bundle.js # or `rollup main.js -f cjs -o bundle.js`
(你也可使用rollup src/main.js > bundle.js
,可是下面你会明白,这种方式在你想要生成map文件时缺少灵活性。)
运行这个代码
node > var myBundle = require('./bundle.js'); > myBundle(); 'hello world!'
祝贺,你已经使用rollup建立了第一个bundle。
目前为止,都还不错,可是当咱们开始添加更多的设置时,这就变成了使人讨厌的在命令行输入(不少)。为了保存咱们本身经常使用的设置,咱们能够建立一个配置文件,里面保存咱们须要的设置。使用js写配置文件比使用命令行方便多了。
在根目录建立一个配置文件,命名rollup.config.js
,而后添加以下代码。
//rollup.config.js export default { entry:'src/main.js', format:'cjs', dest:'bundle.js'//等于--output }
使用 --config or -c flag:来使用该文件。
rm bundle.js//而后检查该命令是否有效。 rollup -c
你可使用相应的命令行命令来覆盖设置文件中的行为。
rollup -c -o bundle-2.js
(注意:rollup是本身运行配置文件,所以咱们可使用export default
语法。语法没有被bable编译,因此你只能使用当前node版本所支持的es2015语法。)
固然,若是你喜欢你能够制定不用的设置文件。
rollup --config rollup.config.dev.js rollup --confog rollup.config.prod.js
不少javaScript项目有一个惯例:在命令行执行npm run build
就可执行建立——不管是什么平台的系统。这个颇有用,由于若是有人想对你的项目有所贡献(即分支之类的),那么他就能够直接去关注源码便可而不用分心去了解用了什么依赖,怎么组合等(如此这样的有,rollup,webpack,gulp或者其余)。他们甚至都不用全局安装,就像咱们在学习第一部分所作的那样。
设置你本身的npm run build
是很好且简单的。
一个package.json文件保存着你的项目的一些重要的信息,包括名字,版本,受权以及以来。(事实上,若是没有package.json文件你不能把你的项目发表到npm库中——若是你是建立一个应用而非lib库,你仍须要一个package.json文件)。
建立package.json最简单的方法是在你项目所在的目录的命令行运行npm init
名来,并跟着提示一步一步来即可。
打开你的package.json文件而且在scripts
属性下添加build
入口:
{ ... "scripts":{ "test":"echo \" Error:no test specified\"&& exit 1", "build":"rollup -c" } }
(这个前提是假设你已经设置了rollup.config.js
文件在你的项目目录中)
到目前为止咱们一直使用的是全局安装rollup。使用本地安装rollup是一个更好的选择,由于任何复制了你项目的人制药运行了npm install
指令,就会获得一个独立兼容(compatible version)版本。
npm install --save-dev rollup #or `npm i -D rollup`
以后注意package.json中的devDependencies
属性将会存在。
{ ..., "devDependencies": { "rollup": "^0.43.0" }, ... }
全部你的npm run
将会寻找本地版原本运行,若是rollup在本地存在的话。
试下下面的命令。
npm run build
npm run dev
实现监控试试编译经过安装rollup watch
你能够建立一个命令,在源码出现变化是实时编译。
npm install --save-dev rollup-watch
package.json
{ ..., "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "rollup -c", "dev": "rollup -c -w" }, ... }
命令rollup -c -w
(rollup --config --watch
缩写)会以监视模式运行rollup。
目前为止,咱们经过入口文件建立了个一简单的bundle,而且使用相对路径导入了一个模块。随着须要打包更复杂的bundle,你常常须要一些灵活的特性——导入从npm下载的模块,经过babel编译模块,使用json等。
为了应对这些咱们使用插件,这些插件会改变rollup在编译时的一些行为。在the rollup wiki中能够找到目前维护的一些插件。
在这个教程里咱们将使用rollup-plugin-json
插件,它可以使rollup导入json文件里的数据。
安装rollup-plugin-json
做为开发时依赖(development dependency)。
npm install --save-dev rollup-plugin-json
(咱们使用--save-der而不是--save是由于个人代码在运行时不是真正的以来这个插件——只是在咱们编译bundle时依赖而已。)
修改你的src/main.js
文件,让他导入package.json而不是src/foo.js
。
import { version } from '../package.json'; export default function () { console.log('version ' + version); }
运行npm run build
,结果回事以下的样子:
'use strict'; var version = "1.0.0"; var main = function () { console.log('version ' + version); }; module.exports = main;
(注意:只有咱们真正所须要的数据才会被导入——version,其余的name,devDependencies等package.json中的属性将会被忽略,这就是tree-shaking的做用。)
在某种状况下,你的项目须要下载npm的第三方模块到你的node_modules
文件夹中。跟其余的如webpack,Browserfy不一样,rollup不知道out of box
,怎么处理这些依赖,咱们须要添加一些设置。
下载一个the answer
依赖,它导出life,universe,everything问题的答案,
npm install --save the-answer # or `npm i -S the-answer`
注意:此处咱们使用的是--save
,所以它被保存到package.json的dependencies
属性中。
若是咱们更新src/main.js
文件。。。
import answer from 'the-answer'; export default function () { console.log('the answer is ' + answer); }
而后运行rollup
npm run build
咱们会看到以下的警告
⚠️ 'the-answer' is imported by src/main.js, but could not be resolved – treating it as an external dependency.
导出来的bundle.js
仍然可以在Node.js下运行,由于import
声明被转化成CommonJS风格的require
语句,可是the-answer
没有放到bundle中,所以咱们须要一个插件。
rollup-plugin-node-resolve插件教会rollup怎么去找到扩展的模块。安装。
npm install --save-dev rollup-plugin-node-resolve
这时运行下npm run build
将不会有错误抛出,bundle包含导入的组件。
有些库导出的是es6模块,因此你可import
——the-answer
就是这种。然而npm的大多数第三方库是CommonJS风格的模块。在其发生改变以前,咱们须要转换CommonJS为ES2015的模块,而后再用rollup处理。
这正是rollup-plugin-commonjs
的功能所在。
注意rollup-plugin-commonjs
必须在其余的插件转化你的模块以前运行——这是为了防止其余插件打断对CommonJS的探测。
假如你正在建立一个库而且有一个同级依赖(即你的库所须要的依赖而不是开发依赖),例如React或者Loadash等。若是你像咱们上面所讲的那样引入其中,你的bundle将会包含他们所有。
import answer from 'the-answer'; import _ from 'lodash';
你能够优雅地处理引入的模块以及bundle。这个李子中,咱们把lodash做为模块,可是the-answer不是。
// rollup.config.js import resolve from 'rollup-plugin-node-resolve'; export default { entry: 'src/main.js', format: 'cjs', plugins: [resolve({ // pass custom options to the resolve plugin customResolveOptions: { moduleDirectory: 'node_modules' } })], // indicate which modules should be treated as external external: ['lodash'], dest: 'bundle.js' };
如今看下,lodash
会被视做外部,而不是打包到你的lib里面。external
关键字接受一个模块的数组或者一个函数,这个函数的参数是模块的名字,若是这个模块应该不被打包到其中,那么返回true。
export default { // ... external: id => /lodash/.test(id) }
若是你是用babel-plugin-lodash
插件来cherry-pick
lodash模块的话,也许会用这个功能。在这个示例中,Babel将会覆盖你的import语句。
import _merge from 'lodash/merge'
external
数组不会处理通配符,所以import将仅仅做为不打包而已。
不少开发者会在他们的项目中使用Babel
,所以他们可使用一些超前的es6特性,这样可以在浏览器和node环境中使用。
同时使用rollup和Babel的最简单的方法是使用rollup-plugin-babel
插件。安装:
npm i -D rollup-plugin-babel
在rollup.config.js
中配置。
// rollup.config.js import resolve from 'rollup-plugin-node-resolve'; import babel from 'rollup-plugin-babel'; export default { entry: 'src/main.js', format: 'cjs', plugins: [ resolve(), babel({ exclude: 'node_modules/**' // only transpile our source code }) ], dest: 'bundle.js' };
在babel可以真正的编译源码以前,你须要一些设置,建立一个新文件src/.babelrc
:
{ "presets": [ ["latest", { "es2015": { "modules": false } }] ], "plugins": ["external-helpers"] }
在这一步有一些东西跟往常不太同样。首先咱们设置modules:false
,不然Babel将会在rollup转化前转化咱们的模块为CommonJS风格,这样就没法实现rollup的目的(tree shaking)。
其次,咱们使用了external-helpers
插件,它使rollup在bundle的头部添加一次'helper',而不是在每一个使用模块的地方包含他们(这是默认行为)。
第三咱们把.babelrc
放在了src文件夹里,而不是项目的跟目录,若是咱们售后须要它,这个容许咱们有不一样的.babelrc
文件对应不一样的需求,例如测试。(针对不一样的需求设置不一样的配置是个好的方法)
如今,在运行rollup以前,咱们须要安装latest
预设以及external-helers
插件。
npm i -D babel-preset-latest babel-plugin-external-helpers
如今运行rollup生成不打了,此时可使用es2015特性了。首先更新下src/main.js
的内容。
import answer from 'the-answer'; export default () => { console.log(`the answer is ${answer}`); }
使用npm run build
运行rollup,而后查看bundle。
'use strict'; var index = 42; var main = (function () { console.log('the answer is ' + index); });
映射能够经过添加--sourcemap
命令行flag实现,也能够经过在配置文件中设置sourceMap:true
属性实现。
什么是‘tree shaking’?
Tree-shaking是活的代码放入——code inclusion,是一种只填加那些使用了的代码的处理,相似于无用代码剔除,而后提升效率。阅读了解更多:Tree-shaking vs Dead-Code-Elimination
为何原生的ES2015的模块系统更优于AMD和CommonJS模块标准?
ES2015是官方标准,很快会被浏览器以及Node.js所实现。它们容许静态分析实现相似tree-shaking这样的效果,而且拥有更高级的特性,如循环引用,实时绑定(live-binding)等。
谁设计了rollup logo?看起来可耐。Julian Lioyd
coming soon...
rollup 返回的是一个Promises,因此gulp能够很容易的集成。
语法跟配置文件很想,可是属性分散到两个不一样的设置里。
构造bundle,而后导出到目标output。
var gulp = require('gulp') rollup = require('rollup') rollupTypescript = require('rollup-plugin-typescript') ; gulp.task('build',function(){ return rollup.rollup({ entry:"./src/main.js", plugins:[rollupTypescript()], }).then(function(bundle){ bundle.write({ format:'umd', moduleName:'library', dest:'./dest/library.js', sourceMap:true }); }) });