街撮りchの中のひとのブログ

webpackでejsを使い、共通要素をインクルードして効率的にやりたいよね。

目次

  1. 1. 数ページのサイトとはいえテンプレ化はしたい、includeを使うと共通要素を外部ファイル化できて効率いいよね。
  2. 2. 初期設定
  3. 3. どんなパッケージを使ってるか(package.json)
  4. 4. ファイル・フォルダ構成
  5. 5. これがindex.htmlとして作られる元のindex.ejs
  6. 6. webpack.config.js

数ページのサイトとはいえテンプレ化はしたい、includeを使うと共通要素を外部ファイル化できて効率いいよね。

サンプルとしてファイルは以下におてます。
https://github.com/shigekitakeguchi/yarn-webpack-ejs

ちょっとした、例えばブランドサイトとかキャンペーンサイト、小規模な企業や組織、お店のサイトというと構成によっては1ページってこともあるけど数ページから20ページくらいの規模になると思う。
いやいやもっとあるよってことになるかもしれないけど今回紹介しようと思うやり方は数ページから20ページくらいの規模のものが便利なんじゃないかな。
それ以上のサイトになるともうちょっと本格的な静的サイトジェネレーターとかを検討したほうが良いと思う。

数ページとはいえヘッダーやフッター、あとmeta要素やナビゲーション、細かいところでいうとGoogle Analitycsの記述ってサイト全体で共通するものを手作業、ベタ書きでやるってちょっと変更とかあるとツラい。ひと昔前だったらサーバー側でssiなんてものもあった。
サーバー管理している人にセキュリティ的懸念があるよと言われながら設定を依頼したりローカルで開発する時はMAMPとか使っているとhttpd.confを変更してでも本番の環境でうまく動かなかったり、そもそも今だったらS3とかもちろんssi使えない。
じゃあどうするかというとmiddlemanだの静的サイトジェネレーターの出番なんだけどmiddlemanでやるとなるともうすべてmiddlemanにおまかせしないとだめだったりする。
それならってことでwebpackでincludeつかえるようなパッケージないかなと探したら思ったよりもなくて調べるとhtml-webpack-pluginってのとejs-render-loaderを組み合わせるとできそうだってことでやってみました。

テンプレートエンジンに何を使うかなんだけど経験的なものだけなんだけどejsでだいたいがおさまるかなというのがある。

EJS Embedded JavaScript templates (https://github.com/mde/ejs)

プログラム的な要素ががっしり使ってHTMLを出力するってことになるとカッコがない、閉じ要素がないってことでJadeの方が見通しが良かったりするんだけど今回はejsです。 Node.jsのフレームワークであるexpressを利用したことない人にはejs馴染みないと思いますが扱いやすいテンプレートエンジンだと思います。

初期設定

1
node -v

まずはお決まりのNode.js入ってるか確認。

1
yarn -v

Yarn(もしくはnpm)も入ってるか確認。個人的には完全にYarnに移行しました。

1
webpack -v

webpackも入っているか確認。どうも2.1なのか2.0からなのかextract-text-webpack-pluginが使えないような 不具合があるようで1.1系を使ってます。

1
webpack --version

もし入ってなかったら今回はバージョン指定してインストールします。

1
yarn add global webpack@1.14.0
1
npm install -g webpack@1.14.0

以下yarnはnpmに置き換えて実行してもらえれば問題なしです。

どんなパッケージを使ってるか(package.json)

node-sassはグローバルで入っているはずなので不要かと思ったのですがエラーはかれたのでインストールしてます。scssをロードしてcssにコンパイルしてってのもいれてます。 もしpost-css的なものがいいとかautoprefixerいれたいとかあれば置き換えてもらえたらと思います。webpack使ってもろもろすると複雑になりがちなのでわかりやすいように最低限な感じです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"name": "yarn-webpack-ejs",
"version": "1.0.0",
"main": "index.js",
"repository": {},
"license": "MIT",
"scripts": {
"start": "webpack -w --config webpack.config.js"
},
"devDependencies": {
"browser-sync-webpack-plugin": "^1.1.4",
"css-loader": "^0.26.1",
"ejs": "^2.5.5",
"ejs-render-loader": "^1.0.0",
"extract-text-webpack-plugin": "^1.0.1",
"html-webpack-plugin": "^2.28.0",
"node-sass": "^4.5.0",
"sass-loader": "^4.1.1",
"style-loader": "^0.13.1"
}
}

ファイル・フォルダ構成

まぁこんな感じの構成になってます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
├── app
│   ├── index.html
│   ├── scripts
│   │   └── bundle.js
│   └── styles
│   └── bundle.css
├── src
│   ├── includes
│   │   ├── footer.ejs
│   │   └── header.ejs
│   ├── scripts
│   │   └── app.js
│   ├── scss
│   │   ├── _normalize.scss
│   │   └── app.scss
│   └── index.ejs
├── package.json
├── webpack.config.js
└── yarn.lock

normalize.scssはわかりやすいように入れているだけです。 yarnなのでyarn.lockというファイルが入ってます。 appの直下がサーバーのドキュメントルートになります。

これがindex.htmlとして作られる元のindex.ejs

src/index.ejsからsrc/includesの中のheader.ejsとfooter.ejsをインクルードしてapp/index.htmlを作ってます。ここではincludesの記述方法をみてもらえれば大丈夫です。

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Title</title>
<link rel="stylesheet" href="styles/bundle.css">
</head>
<body>
<% include includes/header %>
<h1>index</h1>
<% include includes/footer %>
</body>
</html>

webpack.config.js

webpackの設定ファイルです。 html-webpack-pluginというプラグインを使ってHTMLを作ってます。 browser-sync-webpack-pluginはbrowsersync(開いているブラウザすべてで同じ操作ができる的な)の機能だけではなくローカルサーバーとしても使えるので別でサーバー機能のパッケージは使っていません。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var BrowserSyncPlugin = require('browser-sync-webpack-plugin');

module.exports = [{
entry: {
application: './src/scripts/app.js',
},
output: {
path: './app/scripts',
filename: 'bundle.js'
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({
filename: '../index.html',
template: 'ejs-render-loader!./src/index.ejs'
})
]
},{
entry: {
application: './src/scss/app.scss'
},
output: {
path: './app/styles',
filename: 'bundle.css'
},
module: {
loaders: [
{
test: /\.css|scss$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?minimize!sass-loader')
}
]
},
plugins: [
new ExtractTextPlugin('bundle.css'),
new BrowserSyncPlugin(
{
host: 'localhost',
port: 8080,
server: { baseDir: ['app'] },
files: [
'app/scripts/*.js',
'app/styles/*.css'
]
}
)
]
}];

今回ejsにインクルードしてHTMLをレンダリングするためにejs-render-loaderというパッケージを使っています。 HtmlWebpackPluginでtemplateとして扱うindex.ejsにこのように指定します。

1
2
3
4
5
6
7
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({
filename: '../index.html',
template: 'ejs-render-loader!./src/index.ejs'
})
]

複数のページへ共通要素をインクルードすれば効率的にHTMLを管理できると思います。 例えばabout.html(index.htmlとは内容の違うHTML)を作る場合は以下のような感じで指定します。 about.ejsを用意してindex.ejsと同じように共通要素をインクルード指定しpluginsで生成するHTMLのファイル名、元となるejsを指定します。

1
2
3
4
5
6
7
8
9
10
11
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({
filename: '../index.html',
template: 'ejs-render-loader!./src/index.ejs'
}),
new HtmlWebpackPlugin({
filename: '../about.html',
template: 'ejs-render-loader!./src/about.ejs'
})
]

いつもvブログを読んでいただきありがとうございます。
YouTubeチャンネルの運用を続けていくために機材購入、資料購入などで困っております。
よろしければAmazonの欲しいものリストから応援いただけると助かります。

街撮りchの欲しいものリスト

管理人:タケグチシゲキ

フロントエンドエンジニアとして働く55歳のジジイです。
首都圏を中心に散歩動画を撮影してYouTubeで配信してます。現在は夜の街のネオンや光が作り出す陰影が好きで撮影することが多いです。

YouTbueチャンネル

YouTubeチャンネルもぜひご覧ください。思い出の街や気になる街の風景を楽しんでいただければと思います

X(旧Twiiter)

X(旧Twiiter)でも情報発信しております。よろしければフォローいただけると嬉しいです

記事や動画について知っている情報を教えていただけると幸いです。どんなささいなことでも大丈夫です。

また、仕事依頼、コラボ依頼、著作物の提供などについてのお問い合わせは下記のお問い合わせフォーム、X(旧Twiiter)のDMでお待ちしております

お問い合わせ

ブログ記事やYouTubeチャンネルの動画に関するコメント、お仕事依頼、コラボ依頼、著作物の提供についてなどなどお問い合わせにて随時募集中です。
情報提供などもお待ちしております。

お問い合わせはこちらのGoogleフォームからお願いいたします