前端工程化之Rollup構建工具
本文轉載自微信公眾號「DYBOY」,作者DYBOY。轉載本文請聯系DYBOY公眾號。
隨著互聯網行業的發展,前端應用也逐漸變得復雜,所以自然而然地前端工程化開發是必然道路,百家爭名的時代,涌現了許多優秀的構建工具,今天想從學習的角度,和大家分享一下筆者的學習方法和思路。
筆者個人觀點看來,想要完全掌握前端工程化,那么就得對行業現有的構建工具、流程管理、服務管理有一個全面以及深入的認識,無論是前端還是后端開發者,我們通過任意編程語言編寫軟件應用,這是基本能力,但作為工程師,我想那就是得具有工程化的能力,我們應該在開發工程中能夠具有把控全局的能力,有業務上的視野,也得有技術上的沉淀,應該時刻思考,從程序設計、流程設計、方案設計上盡可能得去逼近符合業務場景的最佳實踐。
一、什么是Rollup
Rollup 是一個 JavaScript 模塊打包器,可以將小塊代碼編譯成大塊復雜的代碼,例如 library 或應用程序 —— Rollup文檔
可以理解為,Rollup是一款集成式的代碼打包、應用構建工具。
二、為什么要使用構建工具
如前文所述,前端工程化是作為工程師的必要能力,工程化并非一個人就能搞定的,我們需要站在前人/巨人的肩膀看世界。
隨著行業的發展,涌現了一些獲得行業認可(可以認為是最佳實踐)的構建工具,這些構建工具將一些項目管理和編程開發的行業最佳實踐集成到了一個“腳手架”工具中。如此,便有利于其他團隊快速構建出高效、高質量的工程化項目。
構建工具能做的事:
- 處理兼容性
- 混淆、壓縮代碼
- Tree Shaking
- 轉譯
- 單元測試
- 打包應用
三、上手Rollup
Rollup是一個我認為還比較簡單的構建工具,此處先不去討論其深層次的構建實現細節,先看看如何上手使用。
其實關于Rollup的使用還是比較推薦大家閱讀官方文檔:https://rollupjs.org/guide/
「3.1 安裝」
全局安裝roolup
- yarn add rollup -g
「3.2 簡單使用」
使用rollup打包構建有兩種方式,直接在命令行下需要手打構建必須的參數,當然我們是做工程,那么就得考慮如何盡可能減少團隊成員的上手成本。
為此,Rollup提供了通過文件化配置方式,預設所需的參數,同時通過更改配置文件的參數,可以自由地實現我們自定義的需求。
這里大家可能會想到寫一個CLI,工欲善其事必先利其器,咱先認識工具才能造工具,就先不扯遠了。
3.2.1 創建配置文件
在項目的根目錄或其他你滿意的位置創建一個 rollup.config.js 文件,其內容主要如下:
- export default {
- input: "./src/index.js",
- output: {
- file: "./dist/bundle.js",
- format: "esm",
- name: "RollupLearn",
- },
- }
3.2.2 添加快捷命令
為了簡單,另外再在package.json中配置快捷命令:
- "scripts": {
- "building": "rollup -c -w",
- },
這樣就可以直接在命令行下通過執行:yarn building,就創建了一個實時監聽文件變化就自動重新構建打包的開發環境。
3.2.3 rollup.config.js配置常用參數解讀
官方羅列了rollup的配置參數如下:
- export default {
- // 核心選項
- input, // 必須,打包的入口文件,常見index.js
- external,
- plugins, // 常用:數組中配置一些打包的插件,例如babel等
- // 額外選項
- onwarn,
- // danger zone
- acorn,
- context,
- moduleContext,
- legacy
- output: { // 必須 (如果要輸出多個,可以是一個數組)
- // 核心選項
- file, // 必須,生成的打包文件名&路徑
- format, // 必須,打包構建的目標模塊標準,有cjs、amd、umd、esm、iife等
- name,
- globals,
- // 額外選項
- paths,
- banner,
- footer,
- intro,
- outro,
- sourcemap, // 常用,生成sourcemap文件
- sourcemapFile,
- interop,
- // 高危選項
- exports,
- amd,
- indent
- strict
- },
- };
簡單講一下幾個常用的功能設置
(1)輸入(input -i / --input)
String 這個包的入口點 (例如:你的 main.js 或者 app.js 或者 index.js)
(2)文件(file -o / --output.file)
String 要寫入的文件。也可用于生成 sourcemaps,如果適用
(3)格式(format -f / --output.format)
String 生成包的格式。下列之一:
- amd – 異步模塊定義,用于像RequireJS這樣的模塊加載器
- cjs – CommonJS,適用于 Node 和 Browserify/Webpack
- esm – 將軟件包保存為 ES 模塊文件,在現代瀏覽器中可以通過
- amd – 異步模塊定義,用于像RequireJS這樣的模塊加載器
- cjs – CommonJS,適用于 Node 和 Browserify/Webpack
- esm – 將軟件包保存為 ES 模塊文件,在現代瀏覽器中可以通過 <script type=module> 標簽引入
- iife – 一個自動執行的功能,適合作為<script>標簽。(如果要為應用程序創建一個捆綁包,您可能想要使用它,因為它會使文件大小變小。)
- umd – 通用模塊定義,以amd,cjs 和 iife 為一體
- system - SystemJS 加載器格式
(4)生成包名稱(name -n/--name)
String 變量名,代表你的 iife/umd 包,同一頁上的其他腳本可以訪問它。
(5)插件(plugins)
插件對象 數組 Array (或一個插件對象)。記住要調用導入的插件函數(即 commonjs(), 而不是 commonjs).
(6)sourcemap -m / --sourcemap
如果 true,將創建一個單獨的sourcemap文件。如果 inline,sourcemap將作為數據URI附加到生成的output文件中。
(7)sourcemapFile
String生成的包的位置。如果這是一個絕對路徑,sourcemap中的所有源代碼路徑都將相對于它。 map.file屬性是sourcemapFile的基本名稱(basename),因為sourcemap的位置被假定為與bundle相鄰
如果指定 output,sourcemapFile 不是必需的,在這種情況下,將通過給bundle輸出文件添加 “.map” 后綴來推斷輸出文件名。
(8)treeshake
是否應用 tree-shaking。建議您省略此選項(默認為treeshake:true)
筆者認為,當你需要的再去自行查閱官方文檔,關于這些參數的詳細介紹可參考:https://rollupjs.org/guide/en/#big-list-of-options ,將會是解決問題的最快途徑。
四、增強打包能力
通過上述的一些Rollup本身提供的工具,很容易發現,比如代碼壓縮、代碼混淆、兼容性處理等能力并不具備,但Rollup提供了plugins這項配置字段,它允許我們使用三方庫來增加rollup的構建能力。
在一個項目中,常見需要考慮的問題有:
- 代碼壓縮、代碼混淆
- 兼容性處理
- TypeScript、Less、Sass等轉譯處理
- Tree Shaking(Rollup默認支持并啟用)
- 通用化(支持打包轉譯為umd、cjs、esm等格式的package)
官方提供了一個權威的三方插件參考列表:https://github.com/rollup/awesome ,因此有什么想要增強能力的需要,可以現在該列表中檢索
「4.1 代碼壓縮」
推薦使用:rollup-plugin-terser
安裝:
- yarn add rollup-plugin-terser -D
該插件提供了代碼壓縮,以及是否保留代碼注釋多行展示,一般情況下我們都是全壓縮,并去除代碼注釋,代碼注釋在生產環境并沒什么用。
所以默認配置 terser() 即可。
「4.2 本地http服務」
推薦使用:rollup-plugin-serve
安裝:
- yarn add rollup-plugin-serve -D
一般配置:
- import serve from "rollup-plugin-serve";
- serve({
- open: true, // 運行時自動打開瀏覽器
- headers: {
- "Access-Control-Allow-Origin": "*", // 本地服務允許跨域
- },
- contentBase: ['public'], // 本地服務的運行文件根目錄
- port: 5000, // 設置網絡服務監聽端口
- }),
「4.3 清空生成目錄文件」
每次編譯,如果我們有一些歷史文件,可能會使得我們的生產目錄越來越混亂,因此需要在每次編譯之前清空
推薦使用插件:rollup-plugin-clear
一般使用方法:
- import clear from "rollup-plugin-clear";
- clear({
- targets: ["dist"], // 項目打包編譯生成的目錄
- watch: true, // 實時監聽文件變化
- }),
「4.4 ESlint 代碼格式檢查」
ESLint 是在 ECMAScript/JavaScript 代碼中識別和報告模式匹配的工具,它的目標是保證代碼的一致性和避免錯誤
通過ESlint可以盡可能地規范團隊開發的代碼風格以及通過靜態檢查提升代碼質量。算是一個代碼質量的管理工具吧!
因為ESlint本身涉及到的配置也比較多,在后續會整理或者大家參閱官方文檔:https://eslint.org/docs/user-guide/getting-started
4.4.1 安裝
- yarn add eslint -D
4.4.2 初始化
- yarn run eslint --init
執行這條命令后,會回答一些問題,然后默認配置好一個初始化的ESlint規則的配置文件
初始化完成后,在根目錄創建了一個ESlint的配置文件:.eslintrc.json:
- {
- "env": {
- "browser": true,
- "es2021": true
- },
- "extends": [
- "standard"
- ],
- "parserOptions": {
- "ecmaVersion": 12,
- "sourceType": "module"
- },
- "rules": {
- }
- }
此時,大家在編碼開發的時候就會提示一些不符合規范的語法,同時在VScode中可以提供fix的快捷菜單。
有些配置文件,生成目錄的文件是不需要Eslint檢查,因此可以在項目根目錄新建一個 .eslintignore 文件,例如:
- /dist/
- /public/
- /rollup.config.js
當然ESlint的規則也是比較多的,需要根據自己團隊的成員以及項目本身情況來決定ESlint規則的復雜度。
更多的配置規則可以參閱:https://eslint.org/docs/rules/
4.4.3 配置Rollup支持ESlint
雖然在編碼過程中檢查代碼是否符合ESlint定制的規則,但是我們仍能夠通過Rollup打包成功,因為rollup中并未感知ESlint的規則,所以就得在Rollup的配置文件中配置相關設置。
需要安裝:rollup-plugin-eslint
- yarn add rollup-plugin-eslint -D
配置:
- import { eslint } from "rollup-plugin-eslint";
- eslint(); // 這里沒傳入配置參數,會自動加載文件根目錄的 `.eslintrc.json` 配置文件。
4.4.4 VScode配置
一般大家使用的都是VScode編寫前端項目,所以在團隊項目中,還可以配置一個VScode的工作區配置,大家協同辦公時候就能夠很好地統一一些行為,例如ESlint的在保存代碼的時候自動修復以及自動格式化,盡量減少不統一帶來的風險。
給團隊的開發提效的收益也是非常明顯的,當然一定要根據情況配置合適的代碼規范約束。
「4.5 CSS預處理器插件」
常見的CSS預處理插件有:SCSS、SASS、LESS。
以Less處理器為例子,我們需要安裝:rollup-plugin-less
- yarn add rollup-plugin-less -D
使用例子:
- import { rollup } from 'rollup';
- import less from 'rollup-plugin-less';
- rollup({
- entry: 'main.js',
- plugins: [
- less()
- ]
- });
就可以在打包編譯時候將less文件轉譯為CSS。
「4.6 更多插件」
其實還有很多的插件,其用法如上部分羅列的插件,可見Rollup的使用及上手成本還是相對比較低的,其Tree-shaking是一大亮點,react框架就是用rollup打包的,Rollup小而美,是團隊項目用作構建工具的一個不錯選擇!
筆者暫時也無法給到一個最佳實踐的Rollup插件配置,工程項目都是較為復雜的,剩下的就需要大家根據項目以及團隊本身情況去思考和制定。
五、總結
Rollup打包工具的基本使用就差不多了,通過嘗試可以發現,Rollup的配置等是非常簡單的,改變了開發者的工作形式,以及提升了工作(編碼)效率
“自然者,物見其然,不知所以然;同焉皆得,不知所以得”。作為前端工程師,我們不僅是要會用,還要明白構建的整個過程,這有助于我們在編碼、架構設計上能夠更加合理,或者說更“自然”。