前編からの続きです。
なぜWebpack設定ファイルを分割するのか?
webpackは、「JavaScript」「CSS」「SASS」「画像」などを
- 1つ、または、複数のファイルにまとめる。
- 出力されたファイルを圧縮・難読化する。
などの機能があります。
設定ファイルが複数あれば、
開発時にはJavaScript、CSSはソースマップ付きで読みやすく、リリースビルド時には、圧縮しファイルサイズを小さくする。
開発時には、圧縮関連のプラグインを読み込まずコンパイル時間を短くする。
など、開発時、リリースビルド時で設定を柔軟に変更することができます。
Webpack設定ファイルの分割
今回は、webpack.config.jsを
- 共用
- 開発版
- リリース版
の3つに分割し、開発時は、
共用版 + 開発版
リリースビルド時は、
共用版 + リリース版
を使うようにします。
コマンドラインで作成された「webpack.config.js」は以下の通りです。
それに加え、前編で、リリースビルド用に
- リリースビルド時に、console関数を除去するためのプラグイン
- CSS圧縮プラグイン
を導入しました。
// Generated using webpack-cli https://github.com/webpack/webpack-cli
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const isProduction = process.env.NODE_ENV == "production";
const stylesHandler = MiniCssExtractPlugin.loader;
const config = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "public"),
},
devServer: {
open: true,
host: "localhost",
},
plugins: [
new HtmlWebpackPlugin({
template: "src/index.html",
}),
new MiniCssExtractPlugin(),
// Add your plugins here
// Learn more about plugins from https://webpack.js.org/configuration/plugins/
],
module: {
rules: [
{
test: /\.(ts|tsx)$/i,
loader: "ts-loader",
exclude: ["/node_modules/"],
},
{
test: /\.css$/i,
use: [stylesHandler, "css-loader"],
},
{
test: /\.s[ac]ss$/i,
use: [stylesHandler, "css-loader", "sass-loader"],
},
{
test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
type: "asset",
},
// Add your rules for custom modules here
// Learn more about loaders from https://webpack.js.org/loaders/
],
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
};
module.exports = () => {
if (isProduction) {
config.mode = "production";
} else {
config.mode = "development";
}
return config;
};
webpack.config.jsを分割する準備
まずは、上記ファルをコピーし
- webpack.config.common.js ---共用
- webpack.config.dev.js --- 開発用
- webpack.config.prod.js --- リリースビルド用
の3つのファイルを作成します。
共用部分
開発時、リリースビルド時に共通して必要なものは、
- entryポイント
- output
- 出力先にindex.htmlファイルを作成するHtmlWebpackPlugin
- モジュール部分から、cssとs[ac]ss部分以外
- resolve
です。
モジュール部分の「css」「s[ac]ss」部分は、開発時とリリースビルド時で読み込むモジュールが違うため共通部分から削除し「webpack.config.dev.js」「webpack.config.prod.js」で使用します。
作成した「webpack.config.common.js」から不要な部分を削除したものです。
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "public"),
assetModuleFilename: 'image/[name][ext][query]',
clean: true,
},
plugins: [
new HtmlWebpackPlugin({
template: "index.html",
}),
],
module: {
rules: [
{
test: /\.(ts|tsx)$/i,
loader: "ts-loader",
exclude: ["/node_modules/"],
},
{
test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
type: "asset",
},
// Add your rules for custom modules here
// Learn more about loaders from https://webpack.js.org/loaders/
],
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
};
開発用
開発用には、先ほどのcssモジュール部でのcss関連、開発用サーバーのdevServer関連が共通部分に追加されます。
devServerは通常の「--open」コマンドだと規定のブラウザが開くため、Google Chromeが開くようにします。
Google Chromeは、OSにより記述がことなるためOS判定部分も追加しています。
共通部分にあるものを削除し、必要な部分を追加したものが以下となります。
const { merge } = require('webpack-merge');
const common = require('./webpack.config.common');
const os = require('os');
let devBrowser = 'Google Chrome';
switch (os.platform()) {
case 'win32':
devBrowser = 'chrome';
break;
case 'linux':
devBrowser = 'google-chrome';
break;
default:
break;
}
module.exports = merge(common, {
mode: 'development',
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.s[ac]ss$/i,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
],
},
devtool: 'eval-source-map',
devServer: {
open: {
app: {
name: devBrowser,
},
},
host: 'localhost',
port: 3000,
static: './public',
},
});
リリースビルド用
リリースビルド用には、css関連を圧縮するモジュール、console関数を除去するプラグインをしようするようにしています。
const { merge } = require('webpack-merge');
const common = require('./webpack.config.common');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = merge(common, {
mode: 'production',
plugins: [new MiniCssExtractPlugin(), new CssMinimizerPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
{
test: /\.s[ac]ss$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
minify: TerserPlugin.uglifyJsMinify,
terserOptions: {
compress: {
drop_console: true,
},
},
}),
new CssMinimizerPlugin(),
],
},
});
テスト
webpackの設定ファイルをテストします。
開発用
npx webpack configtest ./webpack.config.dev.js
[webpack-cli] Validate '/Users/yaruo_react_redux/zero-start-react18/webpack.config.dev.js'.
[webpack-cli] There are no validation errors in the given webpack configuration.
リリースビルド用
npx webpack configtest ./webpack.config.prod.js
[webpack-cli] Validate '/Users/yaruo-react-redux/zero-start-react18/webpack.config.prod.js'.
[webpack-cli] There are no validation errors in the given webpack configuration.
スクリプト追加
package.jsonの「script」へ以下を追加します。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config webpack.prod.js",
"build:dev": "webpack --config webpack.config.dev.js",
"build:prod": "webpack --config webpack.config.prod.js",
"start": "webpack serve --config webpack.config.dev.js"
},
Google Chromeで開くかを確認します。
npm run start
以上で、webpack設定ファイルを分割することができました。
ここまでの内容は、以下から取得できます。
git clone -b 04_webpack-config-split https://github.com/yaruo-react-redux/yaruo-start-template-react18.git
また、詳しく解説しているものは、こちらです。