JavaScript 打包器(module bundler)介紹|運作原理與優點

更新日期: 2024 年 11 月 16 日

在現代 JavaScript 開發中,模組化設計已成為標準做法。

我們經常使用像 import x from "dayjs"; 的語法來引用第三方模組。

然而,直接使用這種語法時常會報錯:

Uncaught TypeError: Failed to resolve module specifier "dayjs". Relative references must start with either "/", "./", or "../".

這類錯誤表示 JavaScript 模組,需要使用相對或絕對路徑來引用資源。

例如 ./node_modules/dayjs/dayjs.min.js,而直接使用 "dayjs" 會被認為是無效路徑。

雖然可以手動找到 node_modules 資料夾中的正確路徑來引用,但這樣做既麻煩又容易出錯。

因此,我們通常會使用「打包器」來簡化模組管理流程,並提升開發效率。

什麼是打包器?

打包器(如 Webpack、Parcel、Esbuild、Bun、Vite 等)是將多個 JavaScript、CSS、圖片等資源合併為單一檔案的工具。

打包器的主要目的是將程式中多檔案、多模組的結構統一打包成單一或少量幾個檔案,以便於佈署和管理。

通過打包器,開發者不僅可以有效解決模組引用的路徑問題,還可以優化程式碼、減少請求次數、管理快取等。

打包器的主要功能

  1. 合併文件:將多個 JavaScript、CSS 檔案合併為單一檔案。
  2. Tree Shaking:自動移除未使用的代碼,減少最終打包的檔案大小。
  3. 快取管理:生成帶有版本號的檔案,避免快取問題。
  4. 文件壓縮:通過壓縮代碼減少檔案體積,提升載入速度。

為什麼需要打包器?

打包器的好處,在於它能夠優化網站載入速度,並管理多檔案模組的引用問題,特別是以下幾個方面的優勢:

優點 1:Tree Shaking 與代碼優化

Tree Shaking 是指在打包過程中移除未使用的代碼。

例如,假設在程式中定義了一個變數 var ajijiji = 888;,但該變數從未使用過,打包器就會自動將這段代碼移除。

此外,打包器也會優化變數名稱,比如將 ajijiji 簡化為 n,從而縮小檔案體積。

// 原始代碼
var ajijiji = 888;

// 優化後的代碼
var n = 888;

未使用的變數和函數會被完全刪除,減少了最終輸出的檔案大小。

這樣的代碼優化在大型專案中特別有效,能顯著縮減檔案大小。

優點 2:快取管理

當我們在網站上載入 JavaScript 檔案時,瀏覽器會自動對這些資源進行快取。

這意味著,如果檔案沒有變動,瀏覽器會從快取中加載檔案,而不是重新從伺服器獲取。

但如果檔案有更新,而瀏覽器的快取仍然保存舊檔案,則可能會導致程式出錯。

在傳統方法中,我們通常會在 <script> 標籤後加上時間戳,來強制瀏覽器刷新快取:

<script src="main.js?t=時間"></script>

使用打包器後,每次打包時會自動生成帶有唯一編號的檔案名稱(如 index-xxxx.js)。

當檔案內容變動時,檔案編號也會隨之更新,瀏覽器會認為是新檔案,從而重新載入。

這樣,我們不再需要手動處理快取問題。

<script src="index-編號.js" type="module"></script>

優點 3:減少 HTTP 請求數量(適用於 HTTP/1.1)

在 HTTP/1.1 下,每個檔案的下載請求都需要經過一次握手(handshake),過多的 HTTP 請求會增加網路延遲。

打包器能將多個 JavaScript 或 CSS 檔案合併為一個檔案,從而減少握手次數並縮短載入時間。

但在 HTTP/2 環境下,打包的重要性相對降低,因為 HTTP/2 支援多路複用,可以在一次握手後同時載入多個檔案。

因此,對於 HTTP/2 環境,將過多檔案合併為一個不再是最佳策略。

優點 4:支援多種資源類型

打包器除了可以處理 JavaScript 外,還可以處理 CSS、圖片、字型等資源,並將這些資源整合到最終的打包檔案中,形成完整的應用程式。

這樣,不同類型的資源,可以一同打包並進行版本管理,使佈署流程更加簡單。

案例:使用 Vite 打包器進行快速開發

Vite 是一款輕量級、高效能的打包器,專為現代化 JavaScript 開發而設計。

Vite 利用原生 ES 模組支持,避免了傳統打包器在開發階段的繁瑣步驟,因此它可以顯著縮短開發伺服器的啟動時間和模組加載時間。

這對於依賴大量模組的大型專案尤其有用。

安裝 Vite

要使用 Vite,首先需要將其安裝到專案中。使用以下指令安裝 Vite,並將其作為開發依賴:

npm install -D vite

-D 選項表示將 Vite 安裝為開發依賴,僅在開發環境中使用,而佈署到線上環境時不包含此依賴。

設定 Vite 專案結構

安裝完成後,我們可以創建一個基本的 index.html 作為專案的入口頁面:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Hello Vite</title>
</head>
<body>
  <p>Hello Vite!</p>
  <script src="main.js" type="module"></script>
</body>
</html>

Vite 會自動偵測 index.html 中的 JavaScript 模組並處理其依賴關係。

使用 Vite 的 CLI 指令

package.json 中,可以新增 NPM 腳本指令來啟動 Vite 伺服器,執行各種開發和打包任務:

{
  "scripts": {
    "dev": "vite",           // 啟動開發伺服器
    "build": "vite build",   // 打包專案
    "preview": "vite preview" // 預覽打包結果
  },
  "dependencies": {
    "axios": "^1.7.7",
    "dayjs": "^1.11.13",
    "vite": "^5.4.10"
  }
}

執行以下指令來啟動開發伺服器:

npm run dev

啟動後,終端機會顯示 Vite 的啟動訊息,並提供本地伺服器網址:

VITE v5.4.10  ready in 119 ms

    Local:   http://localhost:5173/

此時,進入 http://localhost:5173/,我們便能看到頁面內容。

點擊打包好的 main.js 檔案,可以確認 Vite 已經自動解決了 import dayjs 的模組路徑問題,無需手動指定 node_modules 的路徑。

Vite 的快取管理與靜態資源優化

Vite 在每次打包後,會自動生成帶有版本編號的檔案,例如 index-xxxx.js。每次檔案

內容變動後,檔案的 hash 值也會跟著改變,瀏覽器會因此重新載入新檔案,而不再依賴舊快取。

這大幅簡化了版本管理問題,讓開發和佈署更加便捷。

此外,Vite 還支援壓縮輸出文件,從而優化檔案大小和傳輸速度。

這些功能讓 Vite 不僅適合開發環境,也非常適合用於生產環境的佈署。

總結

打包器的引入顯著提升了 JavaScript 開發的效率與模組管理的便利性。

通過打包器,我們可以將多個模組、資源整合並壓縮成少數檔案,解決模組引入路徑、資源快取、HTTP 請求優化等問題。

Vite 作為新一代打包工具,專注於提升開發體驗和效能,是現代前端開發的理想選擇。

重點回顧

  1. 打包器的作用:解決模組管理、資源合併、快取優化等問題。
  2. Tree Shaking:自動移除未使用的代碼,減少最終檔案大小。
  3. Cache Busting:生成帶有版本號的檔案名,解決瀏覽器快取問題。
  4. 效能提升:在 HTTP/1.1 環境中減少請求次數,提高載入速度。
  5. Vite 的優勢:使用原生 ES 模組支持,提升開發伺服器的啟動和模組加載速度,特別適合大型項目。

通過合理使用打包器,開發者可以顯著簡化模組管理流程,並提高程式碼的可維護性和載入速度。

Similar Posts

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *