冗餘程式碼都走開——前端模組打包利器 Rollup.js 入門

發表於2016-05-25

之前翻譯過一篇文章,介紹了通過 ES2015 的解構賦值語法引入模組,可以讓打包工具(browserify)最終編譯出來的程式碼量最小化。

殊不知在 webpack 1.X 版本是無法利用該特性來避免引入冗餘模組程式碼的,導致打出來的 bundle 檔案大小難免略有臃腫。

今天則向大家介紹一個當紅炸子雞——Rollup.js,通過它可以讓你的 bundle 最小化,有效減少檔案請求大小——以至於連 vue 都迅速地轉投它來打包模組。

Tree-shaking

在 Rollup 編譯模組的過程中,通過 Tree-shacking 的方式來剔除各模組中最終未被引用到的方法,通過僅保留被呼叫到的程式碼塊來縮減 bundle 的大小。

我們來看下官網的例子。

頁面入口檔案 main.js:

被引如的 math.js 模組如下:

通過 Rollup 打包之後如下:

可以很明顯地體會到 Tree-shaking 的作用 —— Math 模組裡有個從未用到的 square 方法,我們們在 bundle 檔案裡把它消滅掉了。

另外 TS 會抽取引用到的模組內容,將它們置於同一個作用域下,進而直接用變數名就可以訪問各個模組的介面;而不像 webpack 這樣每個模組外還要包一層函式定義,再通過合併進去的 define/require 相互呼叫。

當然這種方法需要 ES2015 的解構賦值語法來配合,多虧了它,Rollup 才能有效地對模組內容進行可靠的靜態分析。

使用方式

安裝自然不用說,走 npm 的老套路:

執行打包的方式也是簡單到爆:

這意味著將入口檔案 src/main.js 打包為 rel/bundle.js 檔案。

很多時候我們開發走的 ES2015 模組語法,但最終編譯出來的模組希望它能走 commonjs 語法,只需要加上 -f cjs 執行時引數(f for format)即可:

當然,如果你想編譯為其它格式,可以把 cjs 更換為:

我們分別來個參考~ 假設入口檔案 src/main.js 如下:

編譯為各種模式後的bundle:

配置檔案

和 webpack 一樣,rollup 也支援通過配置檔案來實現更靈活的功能。

我們在專案根目錄新建一個 rollup.config.js :

然後執行

即可通過預設配置檔案(rollup.config.js)所設定的資訊來進行打包。

如果你的配置檔案另有其名(例如“rollup.config.dev.js”),在後面加上配置檔名即可:

Rollup 也支援使用外掛,寫到配置物件的 plugin 裡即可,這裡我們以 rollup-plugin-babel 為例:

比較不爽的是,babel 的預設不像 webpack 可以直接寫在配置檔案裡,而還是得獨立寫個“src/.babelrc”(注意我們可以寫在 src 下,而不是非得放在專案根目錄下)

注意我們得確保安裝了 rollup-plugin-babel 和 babel 預設 babel-preset-es2015-rollup

這時候就能配合 babel 一起把 ES6 的模組編譯為 ES5 的 bundle 了。

更多有趣的外掛可以在 rollup 專案組織裡找,貌似沒有 webpack 那樣專門有個外掛列表頁彙總,這點找起來不太方便。

Rollup 也支援直接在模組中來被呼叫執行,這樣很方便跟 grunt/gulp 等工具進行協作。

如我們修改 rollup.config.dev.js 內容為:

然後用 node 直接執行

可以得到一樣的執行結果。

注意 “rollup.rollup()”返回一個帶著 bundle 作為 resolve 回撥引數的 Promise 物件,我們常規直接使用語法糖 bundle.write 來打包輸出檔案:

其等價於

SourceMap

為了方便除錯編譯後的檔案,rollup 肯定不會忘記新增 source map 功能,而且其配置也非常簡單:

這樣編譯後,rollup 會自動生成一個 rel/bundle.js.map 關聯到 rel/bundle.js 中。

也可以將其直接內聯在 bundle 裡而不是獨立生成一個 map 檔案:

若希望 map 檔案可以自定義位置和名稱,就得使用上面稍微提到的 bundle.generate 方法了:

issue

Rollup 雖然利用 ES6 的特性幫我們節省了不少檔案大小,但它並沒有類似 webpack 的 -p 引數幫你壓縮混淆檔案。

因此即使是官方文件也推薦配合使用 UglifyJS 來進一步縮小 bundle 體積。

另外 webpack2 已經出來好幾款 beta 版本了,同樣也加上了對 Tree-shaking 的支援,相信 webpack2 出來後,Rollup 的熱度會大大消減。

共勉~

相關文章