webpack 中的 loader 和 plugin 的差別是什麼?

2022年12月30日

💎 加入 E+ 成長計畫 與超過 400+ 位軟體工程師一同在社群中成長,並且獲得更多的軟體工程學習資源

webpack 在前端業界中被廣泛使用,當使用 webpack 時,多半會搭配不同的 loader 或 plugin。假如你有在履歷上提到你會的技術中包含 webpack,那就可能會被問到 loader 與 plugin 分別是什麼、 兩者有什麼不同的問題。

什麼是 loader?

webpack 本身只能處理 .js.json 文件,loader 可以讓 webpack 去處理其他種類的文件,並將這些資源和文件轉換為模組,讓應用程式可以使用、並添加到依賴圖中。以程式的角度來看, loader 本身就是一個 JavaScript 的函式,不同的 loader 即是能處理不同種文件的函式

舉例來說,如果我們想處理 .css文件,可以使用 style-loader 和  css-loader 來處理,透過這兩個 loader,讓原本只懂 JavaScript 與 JSON 的 webpack 也可以處理 css,讓 .css文件能被打包到最終檔案中。

使用 loader

有兩種使用 loader 的方式,一是配置方式 (Configuration),第二種是內聯方式 (Inline)

官方推薦的使用方法是第一種配置方式,使用方法是在  webpack.config.js 文件中指定 loader。我們可以在 module.rules 中指定什麼檔案類型要使用一個或多個 loader,loader 的執行方式會是從右到左依序執行,前一個執行的 loader 會把執行的結果傳遞給下一個 loader,一直到最後一個 loader 會返回 webpack 所需要的檔案。

下方程式碼例子,執行順序會是 sass-loadercss-loaderstyle-loader

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          { loader: "style-loader" },
          {
            loader: "css-loader",
            options: {
              modules: true,
            },
          },
          { loader: "sass-loader" },
        ],
      },
    ],
  },
};

常見的 loader

如下 (更多的 loader 可參考 webpack 官方網站):

  • babel-loader  使用  Babel  將 ES2015+ 程式碼轉換為 ES5
  • esbuild-loader  使用  esbuild  將 ES2015+ 程式碼轉轉譯到 ES6+
  • style-loader  將模組導出的内容作為樣式添加到到 DOM 中
  • css-loader  加載 CSS 文件並解析 import 的 CSS 文件,最终返回 CSS 的程式碼

什麼是 plugin?

loader 的作用是資源模組的轉化,讓 webpack 能處理不同資源;而 plugin 則是用來擴展 webpack 的功能,例如讓 webpack 能對打包的結果進一步優化、做資源管理等。webpack 生命週期中的各個環節會提供鉤子 (hook),供開發者使用。開發者可以在這些生命週期節點透過 Plugin 來做額外操作,進而拓展 webpack 的功能。

從程式的角度來看,loader 是函式,而 plugin 則是帶有 apply 方法的物件,在 apply 方法中註冊 webpack 生命週期提供的鉤子,當運行到該生命週期時,就會回調開發者寫在 apply 中的功能。

使用 plugin

我們在使用 plugin 時,會先透過 require 語法來引入需要的 plugin,並透過 new 實例化,將它添加在 plugins 的陣列當中。如下方程式碼範例

const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");

module.exports = {
  entry: "./path/to/my/entry/file.js",
  output: {
    filename: "my-first-webpack.bundle.js",
    path: path.resolve(__dirname, "dist"),
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: "babel-loader",
      },
    ],
  },
  plugins: [new HtmlWebpackPlugin({ template: "./src/index.html" })],
};

在上面的例子中,HtmlWebpackPlugin 協助在打包的過程中生成一個 HTML 檔案,並自動將所有的打包檔案注入在這個 HTML 文件當中 (詳細的使用方法可以參考此文件)。這是原本 webpack 沒有提供的功能,透過這個 plugin 我們能進一步獲得這功能。


參考資料

🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們