WordPressやコンポーネントの概念があるReactなどのように、htmlでもヘッダーやフッターなど共通部分をテンプレート化して効率的にコーディングをすることが可能です。
実現したいこと
- ヘッダーやフッターなどの共通部分をテンプレート化する
- WordPressやReactなどを使用せずHTMLのみでコーディング
事前準備
npmパッケージのインストール
Webpackのプラグイン html-webpack-plugin と html-loader をインストールします。
npm i --save-dev html-webpack-plugin html-loader
プラグインの基本的な使用方法の説明は省略します。
サンプルサイトの構成
例としてトップページと下層ページの2ページのサイトを作成します。JavaScriptのファイルは common.js
と index.js
の2種作成し、 index.js
はトップページでのみ読み込むようにします。
htmlの作成
テンプレートの header.html
を作成します。単純に共通化したい部分のhtmlを抜き出しただけのファイルです。 src/template/
に保存します。
/** header.html */
<header>
<nav>
<ul>
<li><a href="./index.html">Home</a></li>
<li><a href="./page.html">Page A</a></li>
</ul>
</nav>
</header>
テンプレートを読み込む側の index.html
と page.html
を作成します。テンプレートのhtmlを読み込むには html-loader
を使用します。テンプレートを読み込みたい場所に <%= require('html-loader!ここに読み込みたいhtmlを記述') %>
と記述します。JavaScriptファイルの読み込みは、Webpackのプラグインを使用してbuild後に出力されるhtmlに記述されるようにするため、ここでは記述しません。
page.html
は <title></title>
と <h1></h1>
を変えるだけです。
/** index.html */
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Home</title>
<meta name="description" content="" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
</head>
<body>
<%= require('html-loader!./template/header.html') %>
<main>
<h1>This page is Home</h1>
</main>
</body>
</html>
JavaScriptファイルの作成
src/js/
に common.js
と index.js
も作成します。ファイルの中身は何でも構いません。サンプルでは意図した通りに読み込まれるかを確認するため、以下のようにしています。
/** common.js */
console.log("index.htmlとpage.htmlの両方で読み込まれる");
/** index.js */
console.log("index.htmlでのみ読み込まれる");
webpack configの設定
html-webpack-plugin
を使用して、build後にdistフォルダにhtmlファイルが出力されるように設定します。index.html
と page.html
の2ページ分を記述します。
plugins
に new HtmlWebpackPlugin()
と記述するだけでデフォルトのindex.htmlファイルが出力されますが、プラグインに用意されているオプションでカスタマイズしていきます。
template
には先ほど作成したhtmlファイル(コーディング時に編集するファイル)を記述します。 filename
は記述しない場合デフォルトの index.html
になるため、 index.html
以外のページは必ず記述するようにします。
/** webpack.config.js */
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
common: "./src/js/common.js",
index: "./src/js/index.js",
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
new HtmlWebpackPlugin({
template: "./src/page.html",
filename: "page.html",
}),
],
};
次に index.js (index.min.js)
が index.html
でのみ読み込まれるようにします。
指定したchunkのみを含める chunks: ['含めるentryの名前を記述']
か 指定したchunkを除外する excludeChunks: ['除外するentryの名前を記述']
のどちらかをオプションに記述します。
サンプルサイトでは以下のように、page.html
ではcommon.js (common.min.js)
のみを読み込まれるようにします。
/** webpack.config.js */
new HtmlWebpackPlugin({
template: "./src/page.html",
filename: "page.html",
chunks: ["common"],
});
ここまでで npm run build
を実行すると dist
フォルダにJavaScriptを読み込む <script>
タグを含んだhtmlファイルが生成されます。
html-webpack-pluginのその他のオプション
ページタイトルをwebpackのconfigで管理する
webpackのconfigで title
オプションを使用して、ページタイトルを記述します。例えば index.html
のページタイトルを「Home | サイト名」にする場合は以下のように記述します。
/** webpack.config.js */
new HtmlWebpackPlugin({
title: 'Home | サイト名',
template: './src/index.html'
}),
キャッシュ対策
build後のhtmlで読み込まれるJavaScriptファイルにユニークなhashを付与することができます。オプションの hash
を true
にするだけです。
/** webpack.config.js */
new HtmlWebpackPlugin({
title: 'Home | サイト名',
template: './src/index.html',
hash: true
}),
JavaScriptファイルの読み込む位置を指定する
inject
オプションを使用することで、build後のhtmlでJavaScriptファイルを読み込む <script>
タグの位置を変更できます。指定できるのは true || 'head' || 'body' || false
の4つで、それぞれ以下のようになります。
値 | 説明 |
---|---|
true | body終了タグの直前(bodyを指定した場合と同じ) |
head | head終了タグの直前 |
body | body終了タグの直前(trueを指定した場合と同じ) |
false | <script> タグの記述なし |
デモ・ソース
Source
「Webpackを使用してhtmlの共通部分をテンプレート化」のデモ
最後に
記事内で作成したサンプルサイトのように、テンプレートのhtmlを読み込む側と異なるディレクトリに設置する場合は、画像やリンクのパスの記述に注意が必要です。
参照
- HTML Webpack Plugin https://github.com/jantimon/html-webpack-plugin (2020-2-18参照)
- html-loader https://github.com/webpack-contrib/html-loader (2020-2-18参照)