avatar
threadsinstagram

什麼是 web bundler?

Table of Contents

前言

先做個名詞定義,此系列文中的 bundler 指的都是網頁開發中的模組打包工具 (web module bundler) 的簡稱。

相信網頁開發者對 bundler 應該都不陌生,可能也有聽過 JavaScript 的模組化歷史,秉持著此系列期待是能由淺入深,這邊也簡單做一些前情提要與複習,為後續的介紹梳理一下脈絡。

什麼是 bundler?

參考上面這張圖片,共有三部份分別代表:

  • 輸入:左邊這塊就是在整個 codebase 中的多個程式模組、第三方套件、圖片、樣式等資源,他們在開發過程中會互相引入依賴
  • bundler:就是中間那個黑盒子,能夠在其中調整一些諸如轉譯、合併、刪除不必要的檔案、優化等設定,讓你在打包過程中可以正確識別輸入內容,並輸出成最佳化的內容
  • 輸出:經過 bundler 處理後,打包出能被瀏覽器執行的檔案們

這邊先參考 Webpack 官網的示意圖簡單理解 bundler 的基本用途與概念,後面的章節中將會再對從古至今各款 bundler 做個介紹。

為什麼會需要 bundler?

其實上面已經有提到一部份,再多說詳細些的話就是在開發過程中,我們可能會使用對開發較方便的語法如 React JSX、TypeScript、SCSS 等,或引用各種不同模組化方式打包出的第三方套件,甚至使用較新版標準的語法等。

最後要部署到線上時,為了讓不同瀏覽器能兼容與識別,因此需要用 bundler 幫忙用諸如 babel、loader 等去做轉譯,輸出讓瀏覽器能正確執行 JavaScript、CSS、圖片資源等檔案。

另外 bundler 也能利用本身的特性或一些 plugin 做設定去做諸如 split chunks、tree shaking、uglify、minify 去優化打包出的檔案,達到按需載入、減小 bundle size 的效果。

動手做

Talk is cheap, show me the code!

上面看了許多文字來實際用個小實驗動手體驗一下 bundler 怎麼用。雖然目前許多前端框架或 meta-framework 都有各自現成的 CLI 工具與 starter 可以快速啟動一個新專案,但為了研究用途我們這參考 Webpack 文件的結構來純手工體驗看看。

環境

使用目前較穩定且最新的版本,但理論上不會差太多,附上版本資訊供參考:

  • Node v20.17.0 (LTS)
  • npm v10.8.2

建立專案

執行以下指令:

mkdir webpack-demo
cd webpack-demo
npm init -y
npm install -D webpack webpack-cli html-webpack-plugin webpack-dev-server

新增檔案

建立幾個 demo 用檔案與基礎設定,這邊先簡單用個 hello world 的畫面來實驗是否可以正確執行:

// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
 
module.exports = {
  entry: './src/index.js',
  mode: 'production',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },
  plugins: [
    // 在打包後自動產出 index.html
    new HtmlWebpackPlugin({
      title: 'Webpack Demo',
    }),
  ],
  devServer: {
    // 開啟 HMR 設定
    hot: true,
    // serve 時自動開啟瀏覽器
    open: true,
  },
};

簡單說明下以上的設定:

  • entry:讓 bundler 辨識整個 codebase 的進入點,能在 bundler 的編譯過程中去辨識出整棵語法樹
  • output:打包後的檔案放置位置,使用 clean 設定可以每次在重新打包時自動清掉 dist 底下內容
  • mode:可設定為 developmentproductionnone,這邊為了建置方便設定為 production,另外在下面的 dev script 中用 --mode development 複寫設定
  • plugins:可以加上各種擴充套件像是常見的 HtmlWebpackPluginMiniCssExtractPluginTerserPlugin 等來做一些像是自動產出 HTML 檔案、uglify、minify 等設定
  • devServer:這邊簡單做一些在做本地部署時想開啟的如 HMR 與自動開啟瀏覽器新頁設定
// src/index.js
function rootApp() {
  const element = document.createElement('div');
 
  element.innerHTML = 'Hello webpack';
 
  return element;
}
 
document.body.appendChild(rootApp());

調整指令與實際執行

package.json 調整成這樣:

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "dev": "webpack serve --mode development",
    "build": "webpack",
    "start": "webpack serve"
  },
  "devDependencies": {
    "html-webpack-plugin": "^5.6.0",
    "webpack": "^5.94.0",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^5.1.0"
  }
}

這邊安裝的 webpack 相關套件用的是當前最新版,若未來有版本問題導致無法啟用可以再自行根據文件排除。

簡單說明下這裡 script 的用途:

  • dev:利用 webpack-dev-server 來方便做 local 版本開發,另外因為有在 webpack 設定檔中開啟 HMR (Hot Module Replacement) 設定,執行後可達到調整檔案時不需重整網頁就能看到新版畫面
  • build:執行後可做 production build
  • start:在執行 production build 打包後,可直接執行此指令來利用 webpack-dev-server 來將打包出來的網頁應用 host 起來

當你執行了 npm run build 後,應該可以看到整個專案的結構如下:

webpack-demo/
├── package.json
├── package-lock.json
├── webpack.config.js
├── dist/
   ├── main.js
   └── index.html
├── src/
   └── index.js
└── node_modules/

此時再執行 npm run start 應該就能看到以下畫面,就代表成功了:

hello webpack demo

也可以試著另外使用 npm run dev 並編輯 src/index.js 來實際體驗看看 HMR 的效果。

以上就是個基本的 bundler 設定與用途,有興趣再更進階體驗其他細節的話,也可以試試以下的實驗:

  • 安裝幾個套件如 lodashdayjs 等來測試多檔案及第三方套件引用
  • index.js 改成 index.ts
  • 載入 CSS 檔案
  • 載入 Sass 檔案
  • 載入圖片檔

其中除了第一個外就會需要另外安裝各種 loader 並在設定檔中加入副檔名規則來做轉譯,可參考官方文件再玩玩看。

小結

今天簡單介紹了什麼是 bundler 以及為什麼需要用,並利用一個小小的純手工實驗體驗經典不敗的 Webpack 設定方式,期待還算是淺顯易懂,如果有任何問題歡迎在底下留言討論,我們明天見!

Previous Article

目錄