お役立ちコラム
フロントエンド

Webpackの設定ファイルを開発用と本番用で分割する方法

※本記事には広告が含まれます

今回は、Webpackの設定ファイルを開発用と本番用で分割する方法を解説します。

設定ファイルを分けるメリットは、環境ごとに最適なビルドプロセスを構築できる点です。

例えば、開発環境では「高速なビルドとデバッグのしやすさ(Source Mapなど)」を優先し、本番環境では「表示速度を上げるための最適化(Minifyなど)」を設定することができます。

開発効率を高めたい方は本記事を参考に、ぜひWebpackの設定ファイルの分割方法をマスターしてみて下さい。

※本記事は、Webpack 5(v5.104.1)を使用した環境を前提としています。

Webpackの設定ファイルを開発用と本番用で分割する方法

前回の記事までで、現在の設定ファイル(webpack.config.js)の中身は以下のように設定されています。

(関連記事)Webpackの「Asset Modules」機能を使って画像を処理する方法

今回は、この設定ファイルをベースに、共通設定用・開発用・本番用の3つの設定ファイルを作成していきます。

const path = require("node:path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "production",
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[name].[contenthash].js",
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: (pathData) => {
        return pathData.chunk.name === "main"
          ? "style.[contenthash].css"
          : "[name].[contenthash].css";
      },
    }),
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      inject: "body",
      chunks: ["main"],
    }),
  ],
  module: {
    rules: [
      {
        test: /\.scss$/, 
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "sass-loader",
        ],
      },
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        type: "asset/resource",
        generator: {
          filename: "img/[name].[contenthash][ext]",
        },
      },
      {
        test: /\.html$/,
        use: ["html-loader"],
      },
    ],
  },
};
Webpackの設定ファイルを開発用と本番用で分割する方法
  • STEP. 1:共通設定(common)の切り出し
  • STEP. 2:本番用(prod)と開発用(dev)ファイルの作成
  • STEP. 3:package.jsonのスクリプト設定の追加

STEP. 1:共通設定(common)の切り出し

まずは、本番用と開発用で共通の設定を切り出します。

まずは、本番用と開発用で切り分けたい設定箇所にコメントを残しておきます。

ファイル名は開発用ではハッシュが不要なので、ここも切り分けることにします。

const path = require("node:path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "production", //分割
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[name].[contenthash].js", //分割
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: (pathData) => {
        return pathData.chunk.name === "main"
          ? "style.[contenthash].css" //分割
          : "[name].[contenthash].css"; //分割
      },
    }),
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      inject: "body",
      chunks: ["main"],
    }),
  ],
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "sass-loader",
        ],
      },
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        type: "asset/resource",
        generator: {
          filename: "img/[name].[contenthash][ext]", //分割
        },
      },
      {
        test: /\.html$/,
        use: ["html-loader"],
      },
    ],
  },
};

続いて、webpack.config.jsを複製し、複製したファイル名を「webpack.common.js」に変更します。

このファイルは後で本番用(prod)と開発用(dev)ファイルからrequireで読み込みますが、その際に引数を渡すことで設定値を環境ごとに切り替えられるよう、エクスポートはオブジェクト形式ではなく関数形式にしておきます。

const path = require("node:path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = ({ useHash } = {}) => ({
  mode: "production", //分割
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: useHash ? "[name].[contenthash].js" : "[name].js",
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: (pathData) => {
        return pathData.chunk.name === "main"
          ? useHash
            ? "style.[contenthash].css"
            : "style.css"
          : useHash
            ? "[name].[contenthash].css"
            : "[name].css";
      },
    }),
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      inject: "body",
      chunks: ["main"],
    }),
  ],
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "sass-loader",
        ],
      },
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        type: "asset/resource",
        generator: {
          filename: useHash
            ? "img/[name].[contenthash][ext]"
            : "img/[name][ext]",
        },
      },
      {
        test: /\.html$/,
        use: ["html-loader"],
      },
    ],
  },
});

こうしておくことで、関数呼び出し時に引数を渡してファイル名を切り替えることができます。

mode箇所は各環境のファイルで設定するため、ここでは削除しておきます。

const path = require("node:path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = ({ useHash } = {}) => ({
  // mode: "production", //分割 → 削除
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: useHash ? "[name].[contenthash].js" : "[name].js",
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: (pathData) => {
        return pathData.chunk.name === "main"
          ? useHash
            ? "style.[contenthash].css"
            : "style.css"
          : useHash
            ? "[name].[contenthash].css"
            : "[name].css";
      },
    }),
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      inject: "body",
      chunks: ["main"],
    }),
  ],
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "sass-loader",
        ],
      },
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        type: "asset/resource",
        generator: {
          filename: useHash
            ? "img/[name].[contenthash][ext]"
            : "img/[name][ext]",
        },
      },
      {
        test: /\.html$/,
        use: ["html-loader"],
      },
    ],
  },
});

これで共通設定(common)の切り出しができました。

STEP. 2:本番用(prod)と開発用(dev)ファイルの作成

続いて、本番用(prod)と開発用(dev)ファイルを作成していきます。

webpack.config.jsに戻り、ファイル名を「webpack.prod.js」(本番用)にリネームします。

リネームができたら、共通部分を全部削除してwebpack.common.jsをrequireで読み込みます。

const common = require("./webpack.common.js");

module.exports = {
  mode: "production",
};

あとは、webpack.common.jsから読み込んだ関数を呼び出して返ってくるオブジェクトと、module.exportsの設定オブジェクトをマージする必要があります。

Webpackの設定オブジェクトをマージするには、webpack-mergeというモジュールを利用します。

npm install webpack-merge --save-dev

モジュールのインストールができたら、merge関数を呼び出して2つの設定オブジェクトをマージします。

const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");

module.exports = merge(common({ useHash: true }), {
  mode: "production",
});

これでwebpack.common.jsの共通設定にmode: “production”がマージされた本番用の設定オブジェクトが完成です。

同様に、開発用ファイル「webpack.dev.js」も作成します。

開発用ファイルでは、common関数の呼び出し時にuseHash: falseを渡すことで、ファイル名にハッシュが付与されないようにしています。

また、効率的にデバッグができるよう、devtool: “eval-source-map”を指定しています。

devtoolについては、【Webpack入門】インストール方法とJavaScriptファイルのバンドル手順の記事で、少し触れています。

const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");

module.exports = merge(common({ useHash: false }), {
  mode: "development",
  devtool: "eval-source-map",
});

STEP. 3:package.jsonのスクリプト設定の追加

最後に、package.jsonのスクリプト設定を追加します。

これまでビルドを行う際に、npx webpackとターミナルに打ち込むだけで、webpack.config.jsの内容が参照されていましたが、これはwebpack 側でwebpack.config.jsがデフォルトの設定ファイルとなっているためです。

しかし、これからは本番用にwebpack.prod.js、開発用にwebpack.dev.jsが参照されるようにしたいので、–config オプションで設定ファイルのパスを明示的に指定する必要があります。

# 本番用ビルドの場合
npx webpack --config ./webpack.prod.js

# 開発用ビルドの場合
npx webpack --config ./webpack.dev.js

毎回これらの長いコマンドを打ち込むのは手間なので、package.jsonのスクリプトに登録しておきます。

{
  "name": "webpack-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack --config ./webpack.dev.js",
    "build": "webpack --config ./webpack.prod.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^10.4.24",
    "css-loader": "^7.1.3",
    "css-minimizer-webpack-plugin": "^8.0.0",
    "html-loader": "^5.1.0",
    "html-webpack-plugin": "^5.6.6",
    "mini-css-extract-plugin": "^2.10.0",
    "postcss": "^8.5.6",
    "postcss-loader": "^8.2.0",
    "sass": "^1.97.3",
    "sass-loader": "^16.0.6",
    "style-loader": "^4.0.0",
    "webpack": "^5.104.1",
    "webpack-cli": "^6.0.1",
    "webpack-merge": "^6.0.1"
  }
}

これで、本番用ビルドはnpm run build、開発用ビルドはnpm run devで実行できるようになります。

まとめ

今回は、Webpackの設定ファイルを開発用と本番用で分割する方法を解説しました。

最初は1つのファイルに書いていた設定も、環境ごとに分割することで管理しやすくなります。

ぜひ本記事を参考に、Webpack設定ファイルの分割を試してみてください。

次回は、コードの空白やコメントを取り除いてファイルサイズを削減するminifyの設定について解説します。

今回は以上になります。最後までご覧頂き、ありがとうございました。

Webサイトのスポット修正・保守ならお任せ下さい!

ちょっとした修正や調整をしたいけれど、「制作会社に頼んだら高額になりそう」「どこに相談すればいいかわからない」そんなお悩みはありませんか?

弊所「E-VALUE WORKS」では、テキスト修正や軽微な調整などのスポット対応から、月額での保守・管理(外部Web担当)まで、ニーズに合わせたWebサイトの修正・保守サービスを提供しています。

「これって依頼できる?」という段階でも構いません。まずはお気軽にご相談ください。

E-VALUE WORKS アイコン
HOMEお役立ちコラムフロントエンドWebpackの設定ファイルを開発用と本番用で分割する方法