學習rollup.js模組檔案打包

龍恩0707發表於2017-12-30

學習rollup.js模組檔案打包

一:rollup 是什麼?
Rollup 是一個 JavaScript 模組打包器,可以將小塊程式碼編譯成大塊複雜的程式碼.

webpack 和 Rollup 對比不同點:

webpack支援在專案中使用對專案進行打包,webpack的核心功能包括 code-splitting(按需載入js)和 static assets(資原始檔處理)。

rollup 適合使用在獨立的js庫中進行打包。但是目前還不支援 code-splitting 和 熱更新,更趨向專注於構建分類的js庫,也就是說大多
只會生成一個js檔案來被其他專案依賴,更好地利用 es6 modules的優勢來縮小和優化程式碼。

Tree-shaking
在rollup編譯模組的過程中,通過Tree-shaking的方式來去掉模組中未使用到的程式碼,僅僅保留被我們呼叫到的程式碼來減少檔案的大小。

rollup命令安裝如下:
命令:npm install -g rollup 進行安裝。

比如我們看一個demo程式碼如下:

新建資料夾 roll, 資料夾內有如下檔案 main.js 和 index.js; 及 index.html檔案;

main.js 程式碼如下:

export function aa(x) {
  return x * x;
}

export function bb(y) {
  return y + y;
}

index.js 程式碼如下:

import { bb } from './main.js';

console.log(bb(5)); 

如上程式碼可以看到,main.js 內有兩個函式 aa, 和 bb, 但是在index.js內,並沒有使用aa這個函式,當我們使用 rollup進行模組打包
的時候,會把未呼叫到的函式會去掉,這樣的話,可以使多餘程式碼去掉,使得檔案更小。

rollup 打包有以下幾種方式:
1. 對於瀏覽器 可以有如下命令:

rollup index.js -o bundle2.js -f iife 

最後生成 bundle2.js 程式碼如下樣子:

(function () {
'use strict';

function bb(y) {
  return y + y;
}

console.log(bb(5));

}());

2. 對於Node.js 程式碼如下樣子:(編譯成CommonJS的模組樣子)
rollup index.js -o bundle.js -f cjs
如上命令 -f 是 (--output.format的縮寫),指定了所建立的bundle的型別,這裡是CommonJS(在Node.js中執行的)。
最後生成 bundle.js 程式碼如下樣子:

'use strict';

function bb(y) {
  return y + y;
}

console.log(bb(5));

3. 對於瀏覽器和 Node.js(使用UMD format requires a bundle name):
rollup index.js -o bundle3.js -f umd --name 'myBundle'
最後生成 bundle3.js 程式碼如下樣子:

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
  typeof define === 'function' && define.amd ? define(factory) :
  (factory());
}(this, (function () { 'use strict';

function bb(y) {
  return y + y;
}

console.log(bb(5));

})));

二:使用配置檔案

rollup 也可以和webpack一樣使用配置檔案來進行打包了,rollup的預設配置檔案就叫 rollup.config.js, 我在roll資料夾下 新建一個roll.config.js後,然後新增如下程式碼:

export default {
  input: './main.js',
  output: {
    file: 'bundle4.js',
    format: 'cjs'
  }
}

然後在roll資料夾內, 執行命令 rollup -c 來使用配置檔案,就會在roll專案資料夾內生成 bundle4.js檔案,裡面生成後的程式碼
如下:

'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

function aa(x) {
  return x * x;
}

function bb(y) {
  return y + y;
}

exports.aa = aa;
exports.bb = bb;

注意:Rollup本身會處理配置檔案,所以可以使用 export default的語法,程式碼不會經過Babel等類似工具編譯,所以只能使用
所用node.js版本支援es2015語法。

預設的配置檔案叫 rollup.config.js, 我們也可以叫不同的名字,比如叫 rollup.config.dev.js或roll.config.prod.js,
因此我們允許命令的時候可以如下執行: rollup --config rollup.config.dev.js

rollup 配置選項如下:

input: 這個包的入口點 比如我上面包的入口點為 main.js

output: {
  file: 'bundle4.js',
  format: 'cjs',
  name: 'MyBundle'
}

output.file: 要寫入的檔案,也可以用於生成的sourcemaps。
output.format 生成包的格式,有如下格式:

1. amd -- 非同步模組定義,用於像RequestJS這樣的模組載入器。
2. cjs -- CommonJS, 適用於Node或Browserify/webpack
3. es -- 將軟體包儲存為ES模組檔案。
4. iife -- 一個自動執行的功能,適合作為 <script>標籤這樣的。
5. umd -- 通用模組定義,以amd, cjs, 和 iife 為一體。

output.name: 代表iife/umd 包,同一頁上的其他的指令碼可以訪問,比如:配置檔案如下:

export default {
  input: './main.js',
  output: {
    file: 'bundle5.js',
    format: 'iife',
    name: 'MyBundle1'
  }
}

最後生成 bundle5.js 程式碼變為如下:

var MyBundle1 = (function (exports) {
  'use strict';
  function aa(x) {
    return x * x;
  }
  function bb(y) {
    return y + y;
  }
  exports.aa = aa;
  exports.bb = bb;
  return exports;
}({}));

下面分別看看以 amd, cjs, es, iife 及 umd 打包生成後的檔案進行對比下,看看他們打包後的程式碼分別是什麼樣的:

1-1 amd配置檔案如下(rollup.config.js):

export default {
  input: './main.js',
  output: {
    file: 'amd.js',
    format: 'amd',
    name: 'AMD'
  }
}

打包後生成的amd.js如下:

define(['exports'], function (exports) { 'use strict';
  function aa(x) {
    return x * x;
  }
  function bb(y) {
    return y + y;
  }
  exports.aa = aa;
  exports.bb = bb;
  Object.defineProperty(exports, '__esModule', { value: true });
});

1-2 cjs配置檔案如下(rollup.config.js):

export default {
  input: './main.js',
  output: {
    file: 'cjs.js',
    format: 'cjs',
    name: 'CJS'
  }
}

打包後生成的cjs.js如下:

'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

function aa(x) {
  return x * x;
}

function bb(y) {
  return y + y;
}

exports.aa = aa;
exports.bb = bb;

1-3 es配置檔案如下(rollup.config.js):

export default {
  input: './main.js',
  output: {
    file: 'es.js',
    format: 'es',
    name: 'ES'
  }
}

打包後生成的es.js如下:

function aa(x) {
  return x * x;
}

function bb(y) {
  return y + y;
}

export { aa, bb };

1-4 iife配置檔案如下(rollup.config.js):

export default {
  input: './main.js',
  output: {
    file: 'iife.js',
    format: 'iife',
    name: 'IIFE'
  }
}

打包後生成的iife.js如下:

var IIFE = (function (exports) {
'use strict';

function aa(x) {
  return x * x;
}

function bb(y) {
  return y + y;
}

exports.aa = aa;
exports.bb = bb;

return exports;

}({}));

1-5 umd 配置檔案如下(rollup.config.js):

export default {
  input: './main.js',
  output: {
    file: 'umd.js',
    format: 'umd',
    name: 'UMD'
  }
}

打包後生成的umd.js如下:

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (factory((global.UMD = {})));
}(this, (function (exports) { 
  'use strict';
  function aa(x) {
    return x * x;
  }
  function bb(y) {
    return y + y;
  }
  exports.aa = aa;
  exports.bb = bb;
  Object.defineProperty(exports, '__esModule', { value: true });
})));

所有的配置選項如下:

// rollup.config.js
export default {
  // 核心選項
  input,        // 要打包的檔案
  external,     // 將模組ID的逗號分隔列表排除
  plugins,

  // 額外選項
  onwarn,

  // danger zone 
  acorn,
  context,
  moduleContext,
  legacy,

  output: {
    // 如果需要輸出多個,可以為陣列

    // 核心選項
    file,    // 輸出的檔案(如果沒有這個引數,則直接輸出到控制檯)
    format,  // 輸出的檔案型別(amd, cjs, es, iife, umd)
    name,    // 生成UMD模組的名字
    global,  // 以`module ID:Global` 鍵值對的形式,用逗號分隔開 任何定義在這裡模組ID定義新增到外部依賴
                              
    // 額外選項
    paths,
    banner,  // 在打包好的檔案的塊的外部(wrapper外部)的最頂部插入一段內容
    footer,  // 在打包好的檔案的塊的外部(wrapper外部)的最底部插入一段內容
    intro,   // 在打包好的檔案的塊的內部(wrapper內部)的最頂部插入一段內容
    outro,   // 在打包好的檔案的塊的內部(wrapper內部)的最底部插入一段內容
    sourcemap,
    sourcemapFile,
    interop,

    // 高危選項
    exports,
    amd,
    indent,
    strict
  }
}

三:使用外掛
目前為止,我們通過相對路徑,將一個入口檔案和一個模組建立了一個簡單的bundle.js, 但是當構建非常複雜的時候,我們需要引入npm安裝模組,通過Babel編譯程式碼,和JSON檔案打交道等。因此我們可以使用外掛在打包過程中更改Rollup的行為。

3-1 rollup-plugin-json (使rollup從JSON檔案中讀取資料)
將 rollup-plugin-json 安裝為開發依賴。命令如下:
npm install --save-dev rollup-plugin-json

安裝之前,我們在專案中新建或安裝一個 package.json; 具體安裝不介紹(使用npm init一直Enter鍵即可)。

我們先來更改 main.js檔案程式碼,程式碼變成如下:

import { version } from './package.json';

export default function() {
  console.log('version ' +version);
}

在繼續編輯 rollup.config.js檔案,加入 JSON外掛。
程式碼如下:

import json from 'rollup-plugin-json';

export default {
  input: './main.js',
  output: {
    file: 'pluginjson.js',
    format: 'cjs',
  },
  plugins: [ json() ]
}

最後會生成pluginjson檔案程式碼如下:

'use strict';

var version = "1.0.0";

function main() {
  console.log('version ' +version);
}

module.exports = main;

3-2 rollup-plugin-node-resolve 和 rollup-plugin-commonjs 外掛
這兩個外掛可以讓你載入 Node.js裡面的CommonJS模組。
先安裝這兩個外掛:
npm install --save-dev rollup-plugin-node-resolve rollup-plugin-commonjs

更多關於 rollup 可以看官網 http://www.rollupjs.com/

相關文章