前端模組化與打包工具 (Webpack、Rollup、Parcel) 從把妹角度理解前後端如何和平相處

me
林彥成
2022-10-05 | 3 min.
文章目錄
  1. 1. 模組化載入
    1. 1.1. IIFE (Immediately Invoked Function Expression)
    2. 1.2. Module Pattern
  2. 2. 模組打包工具
    1. 2.1. Webpack
    2. 2.2. Rollup
    3. 2.3. Parcel

模組可以理解是在情場小白在跟女孩相處的過程中卻意外擁有把妹高手前同事提供的 “教戰守則”,同事總會在一些時間、情境時告訴你一些小撇步讓男女之間感情升溫。

打包工具則是在這些 “鍛鍊” 的過程中,讓 “教戰守則” 能夠自然且最佳化的融入到自身進而能夠靈活的運用。

模組化載入

封裝元件最簡單的方式是透過 IIFE 和 Module Pattern 來產生元件模組。

在網路上一篇關於模組化載入 的文章中介紹:

  • AMD (Asynchronous Module Definition): 非同步模組定義,適用於 RequireJS 這類工具供瀏覽器使用
  • CMD (Common Module Definition): 通用模組定義
    • CommonJS: 非瀏覽器的環境中 Node 和 Browserify/Webpack
  • Universal Module Definition (UMD): jQuery 可以看得出來就是運用 UMD 來封裝
  • ES Module: ES6 支援的模組語法,原生寫法就可以達到相同效果

IIFE (Immediately Invoked Function Expression)

IIFE 是一個定義完馬上就執行的 JavaScript function,適合像是透過非同步 CDN 載入的模組使用。

1
2
3
4
5
6
var returnValueOfIIFE = (function () {
var value = "Hello";
return value;
})();
// output:
returnValueOfIIFE; // "Hello"

Module Pattern

搭配閉包 (Closure) 和作用域的特性而產生出來的設計模式,運用 function 會產生 closure 的特性區分出 private, public 的變數以及函式,將方法和變數限制在一個範圍內存取與使用。

底線開頭的變數和功能都是隱藏起來的實作,只有在 function 的作用域中可以存取,最後回傳模組的公開的介面 (API) 提供使用。

底下示範了一個運用 IIFE (Immediately Invoked Function Expression) 來實作的計數器模組,使用 IIFE 的目的是希望一定義就執行,這就是最基本的 Module pattern 了,可以發現 count 就是我們 private 的變數,指能夠透過回傳的 public function 來進行操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const moduleCounter = (function () {
let count = 0;
return {
getValue: function () {
return count;
},
increment: function () {
return ++count;
},
reset: function () {
console.log("reset:" + count);
count = 0;
},
};
})();

moduleCounter.getValue();
moduleCounter.increment();
moduleCounter.reset();

模組打包工具

當載入和打包模組時就需要打包工具,前端三大框架開發時也都推薦使用,常見解決方案為 Webpack、Rollup、Parcel 三種。


圖片來源: https://blog.logrocket.com/benchmarking-bundlers-2020-rollup-parcel-webpack/

前端的專案通常在部屬之前都需要先建置 (build),這個過程就是將相關模組進行整合並編譯成瀏覽器支援度較好的版本同時進行最佳化。

在比較大型的前端專案當中,建置工具可以說是必備,主要協助的工作像是

  • tree-shaking 只加入有用到的部分
  • Dead Code elimination 移除不會使用的
  • Code Splitting 程式碼拆分
  • Minify 最小化

Webpack

Webpack 是幾年前開源主流的打包工具,提供了前端模組化開發方式,將各種靜態資源打包成模組並生成優化過的程式碼,可以從指令或更改 webpack.config.js 來設定各項功能。

  • 提供模組載入的功能,方便的管理程式間複雜的相依性
  • 提供 Hot Reload 也就是程式的熱插拔
  • 提供各式 loader 支援程式碼預處理或後處理 (UglifyJS、Babel Loader)

Webpack 是透過 Node.js 來打包前端元件 (模組) 的工具,使用前須先安裝 Node.js。

不過在前年年底發現了 Webpack,開始使用之後就想:

那到底還要不要清楚了解 AMD、UMD 等等複雜的規範?好像就不重要了 Orz 使用 Webpack 後發現根本沒管那些同步不同步的概念 (所以真的不重要嗎 Orz),最後會輸出成一包最佳化的 Bundle 輸出就可以直接用,是方便好用又很猛的工具。

使用方法:

1
2
3
4
5
6
7
8
9
10
// 官網範例
// src/index.js
import bar from "./bar.js";

bar();

// src/bar.js
export default function bar() {
//
}

export就負責輸出,import負責載進來。

會需要寫一個 webpack.config.js 的配置檔,entry 就是入口,要機器幫你 build 總要說從哪開始,最後 output 的就是包成一包的檔案了。

1
2
3
4
5
6
7
8
9
const path = require("path");

module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
},
};

Rollup

Rollup is a module bundler for JavaScript which compiles small pieces of code into something larger and more complex, such as a library or application.

用途主要是用來封裝模組出來給他人使用,所以配置檔中也特別強調可以輸出各種不同的格式。

1
2
3
4
5
6
7
8
9
// rollup.config.js
export default {
input: "./src/index.js",
output: {
file: "bundle.js",
// CommonJS,適用於 Node 和 Browserify/Webpack
format: "cjs",
},
};

配置檔一樣是指定入口跟結果位置,此外也因應模組會用在不同環境所以提供多種模組封裝的 format

  • amd: 異步模塊定義,用於像 RequireJS 這樣的模塊加載器
  • cjs: CommonJS,適用於 Node 和 Browserify/Webpack
  • es: ES 模塊文件
  • iife: 自執行模塊,適用於瀏覽器環境 script 標籤
  • umd: 通用模塊定義,以 amd,cjs 和 iife 為一體

Parcel

The zero configuration build tool for the web.

只要寫完 html 之後不用設定什麼,執行指令就可以幫你自動熱插拔和打包 JavaScript 模組的功能,開發時就不用一直重新整理。

  1. npm install --save-dev parcel
  2. 加入 html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8" />
    <title>My First Parcel App</title>
    </head>
    <body>
    <h1>Hello, World!</h1>
    <script src="./src/index.js"></script>
    </body>
    </html>
    1
    2
    //index.js
    console.log("hello parcel");
  3. npx parcel src/index.html

喜歡這篇文章,請幫忙拍拍手喔 🤣


share