本文一共七個例子,由淺入深帶你熟悉Rollup。首先把 rollup-demos 這個示例倉庫下載到本地node
mkdir rollup cd rollup git clone git@github.com:qiqihaobenben/rollup-demos.git
準備就緒,正文開始react
如下內容基於Webpack和Rollup這兩個打包工具來展開。 webpack
工具的使用是分場景的,Rollup的使用場景是,你的代碼基於 ES6 模塊編寫,而且你作的東西是準備給他人使用的。 git
有一句經驗之談:在開發應用時使用 Webpack,開發庫時使用 Rollup。github
例如:React、Vue、Ember、Preact、D三、Three.js、Moment 等衆多知名項目都使用了 Rollupweb
優勢
__webpack_require__
, Object.defineProperty
__webpack_require__
, Object.defineProperty
)執行耗時也不容小視。Rollup沒有生成這些額外的東西,執行耗時主要在於Compile Script
和 Evaluate Script
上,其他部分能夠忽略不計缺點
好比打包多個依賴庫,把公共依賴項提出來(Webpack的CommonsChunkPlugin)還有HMR(模塊熱替換)npm
npm install -g rollup
json
Usage: rollup [options] <entry file> Basic options: -v, --version Show version number -h, --help Show this help message -c, --config Use this config file (if argument is used but value is unspecified, defaults to rollup.config.js) -w, --watch Watch files in bundle and rebuild on changes -i, --input Input (alternative to <entry file>) -o, --output.file <output> Output (if absent, prints to stdout) -f, --output.format [es] Type of output (amd, cjs, es, iife, umd) -e, --external Comma-separate list of module IDs to exclude -g, --globals Comma-separate list of `module ID:Global` pairs Any module IDs defined here are added to external -n, --name Name for UMD export -m, --sourcemap Generate sourcemap (`-m inline` for inline map) -l, --legacy Support IE8 --amd.id ID for AMD module (default is anonymous) --amd.define Function to use in place of `define` --no-strict Don't emit a `"use strict";` in the generated modules. --no-indent Don't indent result --environment <values> Settings passed to config file (see example) --no-conflict Generate a noConflict method for UMD globals --no-treeshake Disable tree-shaking --silent Don't print warnings --intro Content to insert at top of bundle (inside wrapper) --outro Content to insert at end of bundle (inside wrapper) --banner Content to insert at top of bundle (outside wrapper) --footer Content to insert at end of bundle (outside wrapper) --interop Include interop block (true by default)
export default { // 核心選項 input, // 必須 external, plugins, // 額外選項 onwarn, // danger zone acorn, context, moduleContext, legacy output: { // 必須 (若是要輸出多個,能夠是一個數組) // 核心選項 file, // 必須 format, // 必須 name, globals, // 額外選項 paths, banner, footer, intro, outro, sourcemap, sourcemapFile, interop, // 高危選項 exports, amd, indent strict }, };
生成瀏覽器可用
//打包main.js到bundle.js 打包格式是當即執行函數 rollup main.js -o bundle.js -f iife
生成Node.js可用
//打包main.js到bundle.js 打包格式是commonjs。 rollup main.js -o bundle.js -f cjs
Node.js和瀏覽器均可用
//打包main.js到bundle.js 打包格式是UMD,這個格式須要一個模塊名 rollup main.js -o bundle.js -f umd --name "myBundle"
運行配置文件
rollup -c
segmentfault
// src/example1/main.js import one from './module1.js'; export default function () { console.log(one); } // src/example1/module1.js export default 'hello world!'
在項目根目錄(以後Rollup運行會默認這個目錄)運行 rollup src/example1/main.js -o dist/example1/bundle.js -f cjs
數組
解析: -f
選項( --output.format
的縮寫)指定了所建立 bundle 的類型,打包時必需要有的選項,不然會報錯。
輸出的格式有amd, cjs, es, iife, umd,能夠把命令行中 -f
後面的 cjs
改成其餘的,看一下生成的bundle.js的內容有什麼不同。對於模塊不熟悉的能夠看一下 很全很全的JavaScript的模塊講解
-o
是 --output.file
的縮寫,若是不寫會默認輸出到命令行終端(標準輸出)。
若是添加更多的選項,上面這種命令行的方式就顯得麻煩了,就得須要 使用配置文件 了。
在項目 src/example2
文件夾下,新建一個 rollup.config.js
文件,寫入如下代碼:
export default { input: 'src/example2/main.js', output: { file: 'dist/example2/bundle.js', format: 'cjs' } }
新建一個main.js
和 module2.js
以下:
// src/example2/main.js import one from './module2.js'; export default function () { console.log(one); } // src/example1/module2.js export default 'hello config!'
接下來就是運行命令,rollup.config.js
原本是Rollup默認運行的配置文件,若是咱們的rollup.config.js
是放在根目錄下的,能夠直接運行rollup -c
,不用任何選項,可是咱們是放在src/module2
文件夾下的,因此要加上配置文件的路徑 rollup -c src/module2/rollup.config.js
注意
rollup -c src/module2/rollup.config.js -o dist/example2/bundle2.js
那麼打包好的文件名就是bundle2.js
export default
語法——代碼不會通過 Babel
等相似工具編譯,因此只能使用支持 ES2015(ES6) 語法的 Node.js 版本。隨着構建更復雜的 bundle,咱們須要加入插件(plugins)。
使用 rollup-plugin-json,令 Rollup 從 JSON 文件中讀取數據。
將 rollup-plugin-json 安裝爲開發依賴,由於代碼實際執行時不依賴這個插件——只是在打包時使用,因此用的是--save-dev
而不是 --save
npm i -D rollup-plugin-json
或者 npm install --save-dev rollup-plugin-json
src/example3
文件夾下新建 main.js
和 rollup.config.js
// main.js import { version} from '../../package.json'; export default function () { console.log(`version is ${version}`); } // rollup.config.js import json from 'rollup-plugin-json'; export default { input: 'src/example3/main.js', output: { file: 'dist/example3/bundle.js', format: 'cjs' }, plugins: [ json() ] }
運行命令 rollup -c src/example3/rollup.config.js
擴展: json函數能夠傳入 include
指定包含文件、exclude
指定排除文件,preferConst
若是爲true
,用const接受輸出,若是爲false
,用 var
接收輸出。
注意: tree-shaking的做用,能夠看到打包好bundle.js中只有version輸入,package.json 中的其它數據被忽略了。
Rollup 不知道怎麼處理依賴於從 npm 安裝到你的 node_modules
文件夾中的軟件包。
例如,添加一個簡單的依賴 the-answer,它輸出對生活、宇宙及其它一切的答案,這個簡單的包是用來演示如何將npm包彙總到Rollup包中。特別是, 此包在package.json
中添加了 "main" (UMD 格式) 和 "模塊" (ES2015 格式)這個兩個選項。
看一下,按照普通流程引入 the-answer
模塊會是什麼結果。 npm install the-answer
在 src/example4
文件夾下新增 main.js
和 rollup.config.js
// main.js import answer from 'the-answer'; export default function () { console.log('the answer is ' + answer); } // rollup.config.js export default { input: 'src/example4/main.js', output: { file: 'dist/example4/bundle.js', format: 'cjs' }, plugins: [ // 沒有加入任何插件 ] }
運行: rollup -c src/example4/rollup.config.js
會有一個警告 Unresolved dependencies
,咱們看一下 打包好的dist/example4/bundle.js
// 截取dist/example4/bundle.js` function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var answer = _interopDefault(require('the-answer')); // 能夠看到the-answer並無打包進來,還得用node的require去請求,而後通過函數轉化才能拿到the-answer的輸出值 // 咱們能夠看一下 node_modules 下的 the-answer 模塊暴露出的內容 var index = 42; export default index; // 這樣也能夠看出,若是the-answer若是打包進來,應該是: var answer = 42;
如今咱們須要一個插件 rollup-plugin-node-resolve 來告訴 Rollup 如何查找外部模塊
npm i -D rollup-plugin-node-resolve
將插件加入配置文件中
import resolve from 'rollup-plugin-node-resolve'; export default { input: 'src/example4/main.js', output: { file: 'dist/example4/bundle.js', format: 'cjs' }, plugins: [ resolve() ] }
再次運行rollup -c src/example4/rollup.config.js
沒有警告 ,咱們看一下打包好的dist/example4/bundle.js
'use strict'; // the-answer的輸出已經打包進來了 var index = 42; function main () { console.log('the answer is ' + index); } module.exports = main;
相似 the-answer
一些庫由於 package.json
裏的module選項可讓咱們正常導入的ES6模塊。 可是目前,npm中的大多數包都是以CommonJS模塊的形式出現的。 在它們更改以前,咱們須要將CommonJS模塊轉換爲 ES2015 供 Rollup 處理。
rollup-plugin-commonjs 插件就是用來將 CommonJS 轉換成 ES2015 模塊的。一般,這個插件會跟 rollup-plugin-node-resolve
配合使用,這樣就能打包 node_modules
依賴中的CommonJS。 rollup-plugin-commonjs
應該用在其餘插件轉換你的模塊以前 - 這是爲了防止其餘插件的改變破壞CommonJS的檢測。
安裝:npm i -D rollup-plugin-commonjs
在 src/example5
文件夾下新建 main.js
和 module5.js
rollup.config.js
, 用來驗證插件。
// module5.js exports.named = 'cfangxu'; //module.exports = {named: 'cfangxu'} 這個會報錯,可是插件文檔裏說是好的,給他提一個issues // main.js import { named } from './module5.js'; export default function () { console.log(named); } // rollup.config.js import resolve from 'rollup-plugin-node-resolve'; import commonjs from 'rollup-plugin-commonjs'; export default { input: 'src/example5/main.js', output: { file: 'dist/example5/bundle.js', format: 'cjs' }, plugins: [ resolve({ jsnext: true, main: true }), commonjs() ] }
注意: 若是引入的是 node_modules
裏的模塊
例如:import { named } from 'my-lib';
要啓用 namedExports
選項顯示的指定命名輸出。固然你也能夠總體都引入
即: import all from 'my-lib';
external 接受一個模塊名稱的數組或一個接受模塊名稱的函數(若是它被視爲外部引用(externals)則返回true)
安裝 lodash
: npm i -S lodash
在 src/example6
文件夾中新建 main.js
和 rollup.config.js
// main.js import answer from 'the-answer'; import _ from 'lodash'; // rollup.config.js import resolve from 'rollup-plugin-node-resolve'; export default { input: 'src/example6/main.js', output: { file: 'dist/example6/bundle.js', format: 'umd', name: 'example6' }, plugins: [ resolve() ], external: ['lodash'] }
配置文件中加入 external
就不會把第三方的庫打包進咱們最後的文件了。能夠在 src/example5/rollup.config.js
中把 external
註釋掉看看打包後的文件,會把整個 lodsh
打包進來。
擴展: 若是用到 lodsh
,可使用 babel-plugin-lodash 來最優選擇lodash模塊。
咱們在項目中有很大機率用到 babel
,使用 Babel 和 Rollup 的最簡單方法是使用 rollup-plugin-babel
安裝: npm i -D rollup-plugin-babel
在 src/example7
文件夾下新建 main.js
.babelrc
rollup.config.js
//main.js import answer from 'the-answer'; export default function () { console.log(`the answer is ${answer}`); } //.babelrc { "presets": [ ["env",{ "modules": false }] ], "plugins": [ "external-helpers" ] } //rollup.config.js import resolve from 'rollup-plugin-node-resolve'; import babel from 'rollup-plugin-babel'; export default { input: 'src/example7/main.js', output: { file: 'dist/example7/bundle.js', format: 'cjs' }, plugins: [ resolve(), babel({ exclude: 'node_modules/**', externalHelpers: true }) ] }
安裝: npm i -D babel-core babel-preset-env babel-plugin-external-helpers
運行:rollup -c src/example7/rollup.config.js
// dist/example7/bundle.js 'use strict'; var index = 42; function main () { // 轉成了ES5的語法了 console.log('the answer is ' + index); } module.exports = main;
說明
babel-plugin-external-helpers
這個模塊是在 .babelrc
文件中體現,目的是讓babel轉義出來的幫助性代碼只在該文件的頭部出現一次,而不會再每一個引入的模塊中加入,若是不想把這些幫助性的代碼打包進你的文件,須要在rollup的配置文件中加入 externalHelpers: true
,這樣就會引用一個全局的babelHelpers
對象