官網 https://cn.rollupjs.org/introduction/
ES 模塊語法:https://cn.rollupjs.org/es-module-syntax/#importing
1. 簡介
將項目分解為較小的獨立部分通常可以使軟件開發更加容易,因為這通常可以消除意外的交互,並大大減少你需要解決的問題的複雜性,在 ES6 版本的 JavaScript 中引入了一種新語法,用於導入導出函數和數據,以便它們可以在單獨的腳本之間共享。
Rollup 是一個用於 JavaScript 的模塊打包工具,它將小的代碼片段編譯成更大、更復雜的代碼,例如庫或應用程序。它使用 JavaScript 的 ES6 版本中包含的新標準化代碼模塊格式,而不是以前的 CommonJS 和 AMD 等特殊解決方案。
Rollup 是一款 ES Modules 打包器。它也可以將項目中散落的細小模塊打包為整塊代碼,從而使得這些劃分的模塊可以更好的運行在瀏覽器環境或者 Node.js 環境。
從作用上來看,Rollup 與 Webpack 非常類似。不過相比於 Webpack,Rollup 要小巧的多。因為 Webpack 在配合一些插件的使用下,幾乎可以完成開發過程中前端工程化的絕大多數工作。而 Rollup 可以説僅僅是一個 ESM 打包器,沒有其它。
除了可以使用 ES 模塊之外,Rollup 還可以靜態分析你導入的代碼,並將排除任何實際上沒有使用的內容。這使你可以在現有的工具和模塊的基礎上構建,而不需要添加額外的依賴項或使項目的大小變得臃腫。
2. 使用
-
創建一個項目
yarn init -
安裝依賴
yarn add rollup -D -
編寫文件
├── package.json ├── src │ ├── index.js │ ├── logger.js │ └── message.js └── yarn.lock -
打包
# Usage: rollup [options] <entry file> yarn rollup ./src/index.js --file dist/bundle.js - 查看輸出文件
從打包結果中看出:
- 代碼結果幾乎沒有發生變化
- rollup 支持 tree shaking,打包的結果中只包含了我們實際使用到的代碼。
rollup 支持 配置文件
-
創建配置文件 rollup.config.js
export default { input: "src/index.js", output: { file: "dist/bundle.js", format: "iife", }, }; -
執行命令
yarn rollup --config rollup.config.js
3. 插件
rollup 自身的能力是 ES 模塊的合併打包,其他項目需求:如 加載其他類型資源模塊、導入 commonjs 模塊、編譯 ECMAScript新特性 ,rollup 支持以插件的形式進行擴展。
插件是 rollup 唯一的擴展形式。
比如 :
加載json文件
-
安裝插件
yarn add rollup rollup-plugin-json -D -
修改配置文件
import json from "rollup-plugin-json"; export default { input: "src/index.js", output: { file: "dist/bundle.js", format: "iife", }, plugins: [json()], }; -
修改 src/index.js 文件,在文件中導入 package.json 文件
// 導入模塊成員 import { log } from "../src/logger"; import message from "../src/message"; import { name, version } from "../package.json"; // 支持結構,沒有使用的部分,會被tree shaking // 使用模塊成員 const msg = message.hi; log(msg); log(`${name}@${version}`); -
執行打包
yarn rollup --config rollup.config.js
加載 npm 模塊
rollup 默認只能按照文件路徑來加載模塊,不能像webpack一樣,通過 模塊名 來引入第三方模塊,為了實現這個特性,需要安裝插件。
-
安裝插件
yarn add rollup-plugin-node-resolve -D yarn add lodash-es -
修改配置文件
import json from "rollup-plugin-json"; import resolve from "rollup-plugin-node-resolve"; export default { input: "src/index.js", output: { file: "dist/bundle.js", format: "iife", }, plugins: [json(), resolve()], }; -
修改 src/index.js
// 導入模塊成員 import { log } from "../src/logger"; import message from "../src/message"; import { camelCase } from "lodash-es"; import { name, version } from "../package.json"; // 使用模塊成員 const msg = message.hi; log(msg); log(`${name}@${version}`); log(camelCase("hello word"));
注意:rollup 默認只能處理 es 模塊,所以使用的是 es 版本的lodash,要使用普通版本的lodash,需要額外處理。
加載 commonjs 模塊
rollup 默認處理 esm 模塊,如果在項目中導入 commonjs 模塊,默認是不被支持的,但是目前有大量的npm包使用了 commonjs 來導出成員,所以為了兼容這些模塊,官網提供了 rollup-plugin-commonjs 插件。
-
安裝插件
yarn add rollup-plugin-commonjs -D -
修改 src/index.js
// 導入模塊成員 import { log } from "../src/logger"; import message from "../src/message"; import cjs from "./cjs-module"; // 導入整個commonjs模塊 // 使用模塊成員 const msg = message.hi; log(msg); log(cjs); - 打包
4. 代碼拆分
使用 ESM 中的動態導入方式,可以實現模塊的按需加載,rollup 內部也會進行代碼拆分。
import() 函數可以用在任何地方,不僅僅是模塊,非模塊的腳本也可以使用。它是運行時執行,也就是説,什麼時候運行到這一句,就會加載指定的模塊。另外,import()函數與所加載的模塊沒有靜態連接關係,這點也是與import語句不相同。import()類似於 Node.js 的require()方法,區別主要是前者是異步加載,後者是同步加載。
-
修改 src/index.js 文件,使用動態導入
import("./logger").then(({ log }) => { log("code split~"); }); -
新增 rollup.config2.js
import json from "rollup-plugin-json"; import resolve from "rollup-plugin-node-resolve"; import commonjs from "rollup-plugin-commonjs"; export default { input: "src/index.js", output: { dir: "dist", // 使用 代碼拆分 時,需要執行 dir,而不是 file format: "amd", // iife 格式 會將結果 打包到一個函數中,不能拆分。因此需要修改 format 格式為 amd,amd可以在瀏覽器環境使用 }, plugins: [json(), resolve(), commonjs()], }; -
打包
yarn rollup --config rollup.config2.js
5. 多入口打包
rollup 同樣支持多入口打包,並且對於多入口中公共的部分也會被抽取出來放在單個文件中作為單獨的bundle。
配置多入口文件,只需要將 配置文件中的 input 屬性修改為數組即可,或者對象配置形式。
需要注意的是,多入口打包時,內部會提取公共模塊,也就涉及到代碼拆分,因此無法使用 iife 的輸出格式,只能輸出為 amd 格式。
6. 瀏覽器
對於 amd 輸出格式的 js 文件,不能直接引入到頁面上,而需要通過實現了 amd 標準的庫(比如 require.js)去加載。
-
新增 dist/index.html 文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script src="https://unpkg.com/requirejs@2.3.6/require.js" data-main="index.js"></script> </body> </html> -
啓動本地靜態服務器
npm install http-server -g http-server dist # 啓動 - 訪問
rollup 優缺點
優點:
- 輸出結果更加扁平
- 自動移除未引用代碼
- 打包結果依然完全可讀
缺點:
- 加載非 ESM 到第三方模塊比較複雜
- 模塊最終都被打包到一個函數中,無法實現 HMR
- 瀏覽器環境中,代碼拆分功能依賴 AMD 😭
如果我們正在開發應用程序,推薦使用 webpack,如果正在開發一個框架或者類庫,可以使用 rollup