常用打包工具筆記

簡介

  • 在專案部署到 Production 環境前,通常會使用打包工具來對前端程式碼做處理
  • 主要目的是將開發中的各種資源和代碼轉換成最終用戶瀏覽器能有效處理的格式
  • 不僅提高性能,也簡化了開發流程,開發者可以專注於程式碼邏輯的實現,而非技術細節

打包工具是什麼?

  • 將眾多模組與資源打包成一包檔案
  • 編譯需要預先處理的內容,變成瀏覽器看得懂的東西,讓我們可以上傳到伺服器

主要幫我們做了以下處理:

  1. 程式碼轉換:
  • 將新版本的 JavaScript(如 ES6 及以上)轉換成大多數瀏覽器能理解的格式
  1. 模區塊合併:
  • 將多個小檔案合併成少數幾個打包檔案,減少 HTTP 請求次數,加快加載速度
  1. 程式碼壓縮:
  • 透過移除多餘的空格、註解、簡化程式碼(如變數名替換)等方式減小檔案大小
  1. 資源優化:
  • 對圖片、字體等靜態資源進行壓縮和優化,進一步提高加載效率
  1. 自動重新整理與熱替換:
  • 在開發過程中實現對程式碼更改的即時反映,無需手動重新整理頁面
  1. 跨瀏覽器相容性:
  • 透過 polyfills 和 transpilers(如 Babel)確保程式碼在不同的瀏覽器上都能正常執行
  1. 環境變數與設定管理:
  • 根據不同的開發階段(開發、測試、生產)調整設定,方便不同環境下的部署

Webpack

功能介紹

  • JavaScript、CSS、圖片等靜態資源視為模區塊,進行合併和打包
  • 透過 Loader,Webpack 能處理各種不同類型的檔案
  • 提供豐富的插件支持,擴展 Webpack 的功能
  • 支持程式碼拆分,提升應用性能
  • 支持熱模區塊替換,提高開發效率

功能配置

  1. entry (入口)
  • 指示 Webpack 從哪個文件開始打包
  1. output (輸出)
  • 指示打包完的文件輸出到哪、如何命名等
  1. loader (加載器)
  • Webpack 本身只能處理js, json等資源,其他資源需要借助 loader,Webpack 才能解析
  1. plugins (插件)
  • 擴充 Webpack 的功能
  1. mode (模式)
  • 開發模式:僅能編譯 JS 中的ES Module語法
  • 生產模式:除了可以編譯 JS 中的ES Module語法,還可以壓縮 JS 代碼
// webpack.config.jsconst path = require('path')module.exports = {  enrty: './src/main.js',  output: {    path: path.resolve(__dirname, 'dist'),    filename: 'main.js'  },  module: {    rules: [      //loader的配置    ]  },  plugins: [    //plugin的配置  ],  mode: 'development'}

參考圖片

  • 啟動 dev server
note-img

Vite

功能介紹

  • 支持 TypeScript、JSX、CSS 預處理器等,無需額外配置
  • 開發環境下,使用原生的 ES 模塊導入功能,允許瀏覽器直接加載模塊而無需打包
  • 生產環境下提供預打包和基於 Rollup 的優化

功能配置

  • 如果要使用插件,例如:vue
  1. 先在devDependencies安裝@vitejs/plugin-vue
  2. vite.config.jsplugins當中配置
// vite.config.jsimport vue from '@vitejs/plugin-vue'export default {  plugins: [vue()]}

在開發環境中

  • 例如修改了一個js檔案

Vite 的處理步驟:

  1. 模區塊檢測與請求:
  • 瀏覽器會根據 HTML 檔案中的<script type="module">標籤發出對 JavaScript 模區塊的請求
  • Vite 接收到這些請求後,會在伺服器端找到對應的檔案
  1. 即時轉換:
  • 對於每個請求的模區塊,Vite 會即時進行必要的轉換
  • 例如將 TypeScript 轉換為 JavaScript、處理 JSX、應用 Babel 轉換等
  • 這種轉換是即時發生的,Vite 不會提前打包這些模區塊,而是在請求時動態進行
  1. 熱模區塊替換(HMR):
  • 當對一個 JavaScript 檔案進行修改並保存時,Vite 會檢測到這一更改
  • 接著會透過 WebSocket 通知瀏覽器,指出哪些模區塊已經更改
  • 瀏覽器隨後會重新請求這些已更改的模區塊。Vite 將處理這些模區塊的即時轉換並發送給瀏覽器
  • 瀏覽器接收到更新後的模區塊,並進行熱模區塊替換
  • 瀏覽器會替換掉舊的模區塊,而不需要重新整理整個頁面
  1. 狀態保留:
  • 在 HMR 過程中,嘗試保留應用的當前狀態

參考圖片

  • 啟動 dev server
note-img

Webpack 和 Vite 的差別

打包策略

Webpack:

  • 採用基於 JavaScript 的模區塊打包方法。在開發和生產階段都會進行原始碼的打包和轉換
  • 在大型專案中,可能導致啟動和編譯時間較長

Vite:

  • 利用瀏覽器原生支持的 ES 模區塊(ESM),在開發階段不進行打包。而是對模區塊進行即時轉換和加載
  • 在生產階段,使用 Rollup 進行打包,比 Webpack 的打包更快

性能優化

Webpack:

  • 提供豐富的優化選項,如程式碼拆分、Tree Shaking 等,但這些屬性通常需要較複雜的設定

Vite:

  • 在開發階段提供快速的冷啟動和即時熱更新,避免不必要的打包

設定複雜度

Webpack:

  • 設定相對複雜,尤其是對於大型或特殊需求的專案。初學者可能需要花費較多時間來學習

Vite:

  • 設計目標是簡化設定過程,提供更多的開箱即用功能,減少了設定的需要

生態系統和社群支持

Webpack:

  • 擁有廣泛的生態系統和社群支持,大量的插件和 loader 可用於擴展其功能

Vite:

  • 雖然比 Webpack 年輕,但已迅速發展,並且與 Rollup 插件相容,提供了豐富的插件選擇

關於編譯工具:Babel

  • 是 JavaScript 的編譯器(compiler)工具,可以把 ES6 標準以上的新語法轉換成最基本的 JS 語法
  • 可以確保代碼在不支持最新語法的環境(例如舊版本瀏覽器)中也能正常運行

功能

  1. 語法轉換(Transpilation)
  • 將新的或未被廣泛支持的 JavaScript 語法轉換為較舊版本的語法
  1. Polyfills
  • 提供一種機制來填充舊環境中缺少的原生對象或方法,例如 Array.prototype.includesPromise
  1. 源碼轉換(Source Transformations)
  • 可以用於轉換 JSX(用於 React)或其他自定義語法
  1. 優化代碼
  • 透過轉換來改進代碼效能或減少文件大小
  1. 插件和預設(Plugins and Presets)
  • Babel 的靈活性來自於其插件體系
  • 預設是一組用於處理常見轉換的插件集合(例如 @babel/preset-env
  1. 源碼映射(Source Maps)
  • 編譯後的代碼會生成源碼映射,以便於調試

在什麼時候會用到 Babel?

  1. 瀏覽器兼容性
  • 當應用需要在不同版本的瀏覽器中運行,尤其是舊版本的瀏覽器
  1. 使用新語法或實驗性功能
  • 例如 Async/Await、Optional Chaining 等
  1. 框架和庫的開發
  • 如 React(JSX 語法)或 Vue(使用了樣板語法和新的 ECMAScript 功能)
  1. 程式碼拆分和 Tree-shaking
  • 在更複雜的前端工程中,可以通過 Babel 實現程式碼拆分和 Tree Shaking,以優化應用
  1. 服務器端和工具開發
  • 雖然 Node.js 通常支持最新的 ECMAScript 功能,但有時仍需要 Babel 來處理特定的轉換或實驗性功能
  1. 開發工作流(Dev Workflow)
  • 與 Webpack、ESLint、Prettier 等工具一同使用,以建立一個高度自定義和優化的開發工作流

參考資料

# Web # Bundler