HTMLとJSを結び付ける

HtmlWebpackPlugin でhtmlとjsファイルを結び付ける。htmlが複数になった場合に、どのHTMLとjsファイルを結び付けるかだけを指定すれば、それ以外は動的に増やせるようにした。

webpack.common.jsのentryで htmlファイルと、そのhtmlの親となるjsファイル名を結び付けている。その値を使用して動的にhtmlファイルを生成する。

しかし、

  • npm script 実行→ webpack.prod.jswebpack.dev.jsが呼び出される→それぞれのファイルでwebpack.common.jsを呼び出し、マージする。
  • devとprodでhtml-webpack-pluginの設定を変えているため、webpack.common.jsの値をwebpack.prod.jswebpack.dev.jsに渡す必要がある。

そのため

  1. webpack.dev.jswebpack.prod.jsにある関数の引数に、webpack.common.jsの結果を渡す。
  2. それぞれのファイルで動的に配列を生成する。

という処理を行う。

// webpack.common.js...module.exports = ({ outputFile, assetFile, envFilePath, assetPath }) => {
return {
entry: {
// htmlが増える毎にここに追記
// htmlページ名:そのhtmlの親となるjsファイル
index: './src/pages/index.js',
'sample/index': './src/pages/sample/index.js',

},

この値をwebpack.prod.jswebpack.dev.jsで使用する。
commonconfig() の返り値がwebpack.common.jsで生成されたオブジェクトとなる。

// webpack.dev.js...module.exports = (env) => {
...
// webpack.common.jsのentryで追加したhtmlファイルを動的に生成する。
const createHtmlPlugins = (entry) => {
const htmpPlugins = [];
Object.keys(entry).forEach((key) => {
htmpPlugins.push(
new HtmlWebpackPlugin({
template: path.resolve(__dirname, `./src/pages/${key}.html`),
// 出力されるファイル名
filename: `${key}.html`,
// headにjsファイルを入れたい場合はheadを指定
inject: 'body',
// 読み込むjsファイルを指定
chunks: [key],
})
);
});
return htmpPlugins;
};
return webpackMerge(
commonConfig({ outputFile, assetFile, envFilePath, assetPath }),
{
mode: 'development',
devtool: 'inline-source-map',
plugins: createHtmlPlugins(
commonConfig({ outputFile, assetFile, envFilePath, assetPath }).entry
),
...

もう少し詳しく説明すると

createHtmlPlugins(
commonConfig({ outputFile, assetFile, envFilePath, assetPath }).entry

commonConfig()の返り値は webpack.common.js で生成されたオブジェクトで、entryはその名の通りentry部分

{
index: './src/pages/index.js',
'sample/index': './src/pages/sample/index.js'
}

このentryのkeyとvalueを利用して、htmlファイルを動的に生成している。

こうすることでhtmlが増えた際は、webpack.common.jsentryに追記していくだけで良い。

htmlが増える毎にwebpack.configを更新しなくてもいい。もっとスマートなやり方がありそうな気がするので、ご存知の方がいたらコメントください。

--

--

Tatsuya Asami
Tatsuya Asami

Written by Tatsuya Asami

Front end engineer. React, TypeScript, Three.js

No responses yet