昔の名残で未だ静的サイトを作る際はAdobe Dreamweaverを使っていますが、重いし何かと不安定なところもあり、使うこと自体辞めたいと思いつつも使っているのは、共通部分をテンプレートとして管理する為だけだったりします。
静的サイトジェネレータやテンプレートエンジンなど色々あるようですが、今回はwebpackを使って比較的簡単な管理をする環境を作ったので、そのメモとして書いておくことにしました。
“html-loader”を使ったものに加え、”ejs-html-loader”を使ったEJS(Embedded JavaScript templates)にも対応しています。
なお、本記事の作成にあたり、下記サイトを参考にさせて頂いております。
Webpackを使用してhtmlの共通部分をテンプレート化 | TIPS
For web developers. React, Next.js, TypeScript, JavaScript, CSS and Web Development.
webpackで静的サイトジェネレータ(EJS編) - Qiita
方針webpackで静的なサイトを生成する需要は一定程度あるようで、既に@toduqさんの大変わかりやすい記事が上がっています。Webpackを頑張って設定して、すごい静的サイトジェネレータとし…
なお、本記事の改良版が下記にあります。
ソースコード
package.json
{
"name": "test",
"version": "1.0.0",
"description": "none",
"main": "index.js",
"scripts": {
"build": "webpack --mode=production",
"build:dev": "webpack --mode=development",
"watch:dev": "webpack --mode=development --watch"
},
"author": "",
"license": "ISC",
"devDependencies": {
"css-loader": "^3.5.3",
"html-loader": "^1.1.0",
"html-webpack-plugin": "^4.2.1",
"ejs": "^2.7.4",
"ejs-html-loader": "^4.0.1",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.14.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"sass-loader": "^8.0.2",
"terser-webpack-plugin": "^2.3.6",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
“ejs”の最新であるv3.xをインストールするとエラーでビルド出来ませんでしたので、v2.xを指定しました。
/src/js/index.js
import "../scss/main.scss";
window.addEventListener('load', function(){
this.console.log('ロード終わったよ!');
}, false);
/src/scss/main.scss
body {
* {
color:#777;
}
}
/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>
/src/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>
/src/page.html
同上
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Sub</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>Sub</h1>
</main>
</body>
</html>
/src/index2.ejs
EJSを使ってHTMLを生成する場合の元ファイルの例です。外部ファイルをincludeしています。※内容は適当です
<!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>
<%
var menuitem = {
menu1: 'メニュー1',
menu2: 'メニュー2'
};
%>
<%- include('template/_head', {nav: menuitem}) %>
<main>
<h1>This page is Home</h1>
</main>
</body>
</html>
/src/template/_head.ejs
“index2.ejs”からロードするヘッダーのテンプレートです。
<header>
<nav>
<ul>
<li><a href="./index.html"><%= nav.menu1 %></a></li>
<li><a href="./page.html"><%= nav.menu2 %></a></li>
</ul>
</nav>
</header>
webpack.config.js
const path = require('path');
const webpack = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/js/index.js'
},
output: {
filename: './js/bundle.js', //JSの出力先
path: path.resolve(__dirname, 'dist')
},
optimization: {
minimizer: [
new TerserPlugin({}),
new OptimizeCssAssetsPlugin({})
]
},
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
url: false
}
},
'sass-loader',
],
}
]
},
plugins: [
//ここから 出力ファイルの設定
new HtmlWebpackPlugin({
template: './src/index.html',
hash: true
}),
new HtmlWebpackPlugin({
template: './src/page.html',
filename: 'page.html', //出力名がindex.html以外の場合は指定が必要
hash: true
}),
new HtmlWebpackPlugin({
template: './src/index2.ejs', //EJSを使ったパターン
filename: 'ejs.html'
}),
//ここまで 出力ファイルの設定
new MiniCssExtractPlugin({
filename: './css/style.css' //CSSの出力先
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
}),
]
}
HTML Webpack Pluginには、テンプレート内に記述した変数に値を指定する等、色々とオプションがあります。
GitHub - jantimon/html-webpack-plugin: Simplifies creation of HTML files to serve your webpack bundles
Simplifies creation of HTML files to serve your webpack bundles - jantimon/html-webpack-plugin
ビルド
本番環境用なら”npm run build”、デバッグ環境用なら”npm build:dev”か”npm watch:dev”(自動ビルド)を実行します。