もともと1枚の静的HTMLで作っていた事業用サイト。
こちらに少しページを足したくなったのですが、いざ静的HTMLでページを増やそうと思うと、ちょっとした悩みが…
「HTMLファイルを増やして後からヘッダーとかフッターとか変更した時に各ページにコピペは面倒だなぁ… パーツ化して使えるようにしたいなぁ…」
ということで、やり方は色々あると思いますが、今回はお勉強を兼ねて「Pug」というテンプレートエンジンを使ってみました!
その入門備忘録をまとめます
目次
Pugとは
今回はざっくりとした説明とさせていただきますが、「Pug」とはHTMLを書くためのJavaScriptテンプレートエンジンです
Pugで書いたファイルはサーバー上にアップロードしてもそのままWebページとしては表現できないので、Pug→HTMLに変換する必要があります
Sassを使ったことがあれば、Sass→CSSに変換して使う…といった流れに似た形になりますのでイメージしやすいかと思います!
今回やりたかったこと
今回Pugに入門するにあたり、期待していたことはこちら▼
- ページ自体は静的なHTMLで作りたい
- header,footerなど各ページ共通な部分はパーツ化して変更に強い状態にしておきたい
とりあえずコレだけ。
他の方法もあったかもしれませんが、ひとまずキーワード的に頭にあったのと、gulpで簡単に開発環境構築できそうだったのでPugを使ってみることにしました
Pugの書き方と開発環境構築
まずはPugの構文についてのまとめと、gulpでの開発環境についてまとめます
Pugの書き方
※各コードの説明の先頭行にある//Pug
,<!--HTML-->
は本記事での説明用に付けているもので、実際の変換結果とは違います。ご了承下さい
タグの書き方
PugでHTMLタグを書く場合、「[HTMLタグ] + スペース + テキスト」のように書いていきます
閉じタグなどは必要ありません
// Pug
p ああああ
<!-- HTML -->
<p>ああああ</p>
入れ子の書き方
Pugはインデントで階層を表現します
インデントはスペースでもタブでも大丈夫ですが、スペースとタブが混在するとエラーになるので注意が必要です
(Editorconfig等で固定しておくと安心)
// Pug
h1 第1階層
div
h1 第2階層
div
h1 第3階層
div ああああああ
<!-- HTML -->
<h1>第1階層</h1>
<div>
<h1>第2階層</h1>
<div>
<h1>第3階層</h1>
<div>ああああああ</div>
</div>
</div>
id,classの付け方
id,classは#
,.
を使って表現します
Emmetを使ったことがあれば特に難しいことは無いと思います
idとclassをつける順に指定はなく、複数のクラスを付ける場合はそれぞれ.
でつなげていきます
// Pug
div#id-sample
div.class-sample
div.class-sample#id-sample.class-sample2.class-sample3
<!-- HTML -->
<div id="id-sample"></div>
<div class="class-sample"></div>
<div class="class-sample class-sample2 class-sample3" id="id-sample"></div>
属性の付け方
a
タグのhref
だったり、title
などの属性は「HTMLタグ + (
属性)
」の形で書いていきます
// Pug
a(href="#") コレはリンクです
img(src="hoge.jpg" title="画像")
div(v-bind:title="message")
<!-- HTML -->
<a href="#">コレはリンクです</a>
<img src="hoge.jpg" title="画像"/>
<div v-bind:title="message"></div>
テキストを改行する
長い文章などを改行して書きたい場合は|
とbr
を使います
// Pug
p
| 1行目
br
| 2行目
<!-- HTML -->
<p>1行目<br/>2行目</p>
HTMLタグをそのまま書く
HTMLタグの後ろに.
を付けて入れ子にすることで書いたタグをそのままHTMLに反映してくれます
// Pug
div.
<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3211.764543391398!2d139.05838716530198!3d36.39069363003499!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x601ef322960966dd%3A0xcfe5b33052dd7d72!2z44CSMzcxLTAwMjYg576k6aas55yM5YmN5qmL5biC5aSn5omL55S677yR5LiB55uu77yRIOe-pOmmrOecjOW6gQ!5e0!3m2!1sja!2sjp!4v1512255596808" width="600" height="450" frameborder="0" style="border:0" allowfullscreen></iframe>
<!-- HTML -->
<div>
<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3211.764543391398!2d139.05838716530198!3d36.39069363003499!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x601ef322960966dd%3A0xcfe5b33052dd7d72!2z44CSMzcxLTAwMjYg576k6aas55yM5YmN5qmL5biC5aSn5omL55S677yR5LiB55uu77yRIOe-pOmmrOecjOW6gQ!5e0!3m2!1sja!2sjp!4v1512255596808" width="600" height="450" frameborder="0" style="border:0" allowfullscreen></iframe>
</div>
コメント
Pugのコメントは行の先頭に//
を書きます。
また、//-
のように二重スラッシュの後にハイフンをつけることでHTMLに残らないコメントにできます
// Pug
// コメント
//- HTMLに変換されないコメント
<!-- HTML -->
<!-- コメント -->
Pugの開発環境をgulpで構築
自分がいつも使っているということもありまして、本記事ではgulpを使ってPugの開発環境を構築してみます
▲今回はこんな感じなフォルダ構成になるようにしてみました
pugフォルダ以下の階層はHTML変換後も保ってくれるのでひと安心
gulpのインストール
※npm init
等は済んでいるものとします
gulp
とPugの変換に必要なパッケージgulp-pug
をインストールしておきます
$ npm install gulp --save-dev
$ npm install gulp-pug --save-dev
gulpfile.js
今回は以下のようなgulpfile.js
を用意しました
var gulp = require('gulp');
var pug = require('gulp-pug');
var src_pug = [
'./src/pug/**/*.pug',
'!./src/pug/**/_*.pug'
];
gulp.task('pug', function(){
return gulp.src(src_pug)
.pipe(pug({
pretty: true
}))
.pipe(gulp.dest('./'));
});
準備ができたら以下のコマンドでPug→HTMLの変換を実行します
$ gulp pug
無事変換が出来ればOKです
Pugファイルの変更を監視して自動で変換する
これまでの状態だと、Pug→HTMLの変換は毎回コマンドを叩く必要がありますので、ファイルの変更があったら自動で変換してくれるようにカスタマイズしてみます
ファイル監視用のパッケージとエラー処理用のパッケージをインストールします
$ npm install gulp-watch --save-dev
$ npm install gulp-plumber --save-dev
gulpfile.js
も編集します
var gulp = require('gulp');
var pug = require('gulp-pug');
var plumber = require('gulp-plumber');
var watch = require('gulp-watch');
var src_pug = [
'./src/pug/**/*.pug',
'!./src/pug/**/_*.pug'
];
gulp.task('pug', function(){
return gulp.src(src_pug)
.pipe(plumber({
errorHandler: function(err){
console.log(err.messageFormatted);
this.emit('end');
}
}))
.pipe(pug({
pretty: true
}))
.pipe(gulp.dest('./'));
});
gulp.task('watch',['pug'],function() {
watch( './src/pug/**/*.pug', function(event) {
gulp.start('pug');
});
});
あとは以下コマンドを1回実行すれば、ファイルが変更されるたびに自動でPug→HTMLの変換を実行してくれます
$ gulp pug
おまけ:atomユーザーはlanguage-pugを入れておくといい
僕はエディタにatomを使っているので、atomの話を少し…
もし、pugファイルを編集中にシンタックスハイライトが効かない場合は「language-pug」というパッケージをインストールすることをオススメします
だいぶ編集しやすくなると思います
Pugファイルを分割してパーツごとに読み込む
これまでPugの基礎的な部分を学んだので、ここからは実際にやりたかった「パーツごとに分割したファイルをくっつけて1つのHTMLを作る」ということに挑戦します
「include」でファイルを読み込む
別のPugファイルを読み込むためにはinclude
という構文を使います
今回は例としてindex.pug
からinc/_header.pug
ファイルを読み込んで1つのHTMLを作ってみます
※読み込むファイルはindex.pug
と同階層にinc
というフォルダを作りその中にまとめて置きました
// index.pug
doctype html
html(lang="ja")
head
meta(charset="utf-8")
title Pugに挑戦
body
include inc/_header
main
h2 コンテンツ部分です
p コンテンツコンテンツコンテンツ…
// inc/_header.pug
header
h1 ここはヘッダーです
include
につづいて読み込むファイルまでのパスを記述します
includeするファイルの拡張子は省略して書くことができます
出来上がったHTMLはこちら▼
<!-- index.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Pugに挑戦</title>
</head>
<body>
<header>
<h1>ここはヘッダーです</h1>
</header>
<main>
<h2>コンテンツ部分です</h2>
<p>コンテンツコンテンツコンテンツ…</p>
</main>
</body>
</html>
無事、index.pug
と_header.pug
を組み合わせて1つのHTMLファイルを作ることができました!
「extends」でレイアウトを継承する
includeだけでも僕のやりたいこととしては十分そうですが、extends
(継承)を使うと複数ページを作る時にもっと効率よくできそうなので頑張って覚えてみます
まずはHTMLの型とでも言ったらいいでしょうか…レイアウトを定義するファイルを用意します
// layout/_layout.pug
doctype html
html
head
meta(charset='utf-8')
block title
body
include ../inc/_header
block content
h1 Default Content
include ../inc/_footer
_layout.pug
でincludeしている_header.pug
と_footer.pug
はこちら▼
// inc/_header.pug
header
h1 ここはヘッダーです
// inc/_footer.pug
footer
p フッター
ここまでのファイルは個々のページで読み込むファイルになります。
実際に作成するページをindex.pug
として作ってみます
// index.pug
extends layout/_layout
block title
title Pugの練習
block content
section
h1 ココはコンテンツ部分
section
h1 block + [ブロック名]で対応するブロックの内容を書いていきます
先頭のextends layout/_layout.pug
で、_layout.pug
を元にページを構成していきます
extends
より下に書かれているblock [ブロック名]
は_layout.pug
内のblock [ブロック名]
に対応しています
対応する_layout.pug
内のblockの内容がindex.pug
に書いたblockの内容に置き換わります
block [ブロック名]
部分を個々のページで拡張していくイメージですかね
出来上がったHTMLはこんな感じになります▼
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Pugの練習</title>
</head>
<body>
<header>
<h1>ここはヘッダーです</h1>
</header>
<section>
<h1>ココはコンテンツ部分</h1>
</section>
<section>
<h1>block + [ブロック名]で対応するブロックの内容を書いていきます</h1>
</section>
<footer>
<p>フッター</p>
</footer>
</body>
</html>
_layout.pug
でincludeしたヘッダー・フッターが展開されていることはもちろん、index.pug
に書いたblock
の内容がちゃんと展開されました!
まとめ
それでもページ内の要素をパーツごとに分割して使えるのは非常にありがたいですね
あとは、pugファイル内で変数やfor文が使えるなど、プログラミングチックなことも出来るようなので、徐々に挑戦していきたいと思います。
今回お勉強に使ったファイルはGitHubに上がっています▼
Pug→HTMLへ変換する為の環境を用意しなければならないという点がEmmetに比べてちょっと面倒ですが、LP制作案件とか来たら効率よくなりそうなので仲良くしていこうと思います!
ワンワン
ではまた。