Skip to content
⚠️ This article was written in 2018. Some content may be outdated.

Webpack の loader と plugin の違い

Webpackの設定でmodule.rules(loader)とpluginsは最も重要な2つの設定項目ですが、違いを混同している人が多いです。

核心的な違い

Loader:ファイル変換器
  - 個々のファイルに作用する
  - AタイプのファイルをWebpackが理解できるJSモジュールに変換する
  - import/require時にトリガーされる

Plugin:ビルドプロセスの拡張
  - ビルド全体のフローに作用する
  - Webpackのライフサイクルイベントを監視し、適切なタイミングで追加処理を行う
  - 機能は強力だが、設定も複雑

Loader:ファイル変換

javascript
module.exports = {
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: "vue-loader", // .vueファイル → JSモジュール
      },
      {
        test: /\.tsx?$/,
        use: "ts-loader", // TypeScript → JS
      },
      {
        test: /\.scss$/,
        use: [
          "style-loader", // 3. CSSをDOMに注入
          "css-loader", // 2. @importとurl()を処理
          "sass-loader", // 1. SCSS → CSS(右から左に実行)
        ],
      },
      {
        test: /\.(png|jpg|gif)$/,
        use: {
          loader: "url-loader",
          options: {
            limit: 8192, // 8KB未満はbase64に変換
          },
        },
      },
    ],
  },
};

Loaderの実行順序は右から左、下から上

javascript
use: ["style-loader", "css-loader", "sass-loader"];
// 実行順序:sass-loader → css-loader → style-loader

Plugin:ビルドの強化

javascript
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
const webpack = require("webpack");

module.exports = {
  plugins: [
    // HTMLを自動生成し、scriptタグを注入
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      filename: "index.html",
    }),

    // CSSを独立ファイルに抽出(<style>への注入ではなく)
    new MiniCssExtractPlugin({
      filename: "css/[name].[contenthash:8].css",
    }),

    // バンドルサイズを分析(必要な時だけ有効化)
    process.env.ANALYZE && new BundleAnalyzerPlugin(),

    // グローバル定数を定義
    new webpack.DefinePlugin({
      "process.env.API_URL": JSON.stringify(process.env.API_URL),
    }),
  ].filter(Boolean),
};

簡単なLoaderを自作する

javascript
// my-loader.js
module.exports = function (source) {
  // source:ファイルの元の内容(文字列)
  // 戻り値:変換後の内容

  // 例:ファイル内のすべてのconsole.logを削除
  return source.replace(/console\.log\(.*?\);?\n?/g, "");
};

簡単なPluginを自作する

javascript
class BuildTimePlugin {
  apply(compiler) {
    // done(ビルド完了)イベントを監視
    compiler.hooks.done.tap("BuildTimePlugin", (stats) => {
      const time = stats.endTime - stats.startTime;
      console.log(`\nビルド時間:${time}ms\n`);
    });
  }
}

module.exports = BuildTimePlugin;

まとめ

LoaderPlugin
作用範囲個々のファイルビルド全体のフロー
トリガーファイルのimport時Webpackのライフサイクルフック
設定場所module.rulesplugins配列
典型的な用途ファイル形式変換圧縮・コード分割・HTML生成・変数注入

MIT Licensed