このページではHTMLを生成するJavaScript製テンプレートエンジンのPugについて解説します。
※Pugは元々Jadeという名称でしたが2016年3月、Pugという名称に変更されました。
目次
1. テンプレートエンジンによるテンプレート作成
2. include(インクルード)
3. extends(継承)
4. mixin(ミックスイン)
5. まとめ
1. テンプレートエンジンによるテンプレート作成
こちらの記事ではJade改めPugの基本的な使い方を紹介しました。
今回はさらにメリットを活かすことができるinclude(インクルード)とextends(継承)、mixin(ミックスイン)について説明します。
こちらでも説明している通り、HTMLのみでは複数にまたがるページで、共通部分を管理するのが少々手間となります。Pugを始めとするテンプレートエンジンではそれが格段に楽になります。
Pugでは、include(インクルード)とextends(継承)、mixin(ミックスイン)を使って、HTMLのテンプレートを作ってゆきます。
以下で、一つ一つ説明してゆきたいと思います。
2. include(インクルード)
まずは以下のファイルを同じディレクトリに作成しましょう。
■page1.pug
doctype
html(lang='ja')
head
meta(charset='utf-8')
title Hello, Pug include
body
div.content
p ページ1 コンテンツ
include footer.pug
■page2.pug
doctype
html(lang='ja')
head
meta(charset='utf-8')
title Hello, Pug include
body
div.content
p ページ1 コンテンツ
include footer
■footer.pug
div.footer
p フッター
page1.pug、page2.pugをそれぞれコンパイルします。
ファイル名を続けて記載することでまとめてコンパイルできます。
pug page1.pug page2.pug --pretty
すると、footer.pugの内容が読み込まれたhtmlが生成されます。
■page1.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Hello, Pug include</title>
<body>
<div class="content">
<p>ページ1 コンテンツ</p>
<div>
<div class="footer">
<p>フッター</p>
</div>
</body>
</html>
■page2.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Hello, Pug include</title>
<body>
<div class="content">
<p>ページ2 コンテンツ</p>
<div>
<div class="footer">
<p>フッター</p>
</div>
</body>
</html>
SSIやサーバーサイド言語でのincludeを知っている方であれば説明いらずですが、各ページでフッターを共通化したい場合、footer.pugというファイルを作っておいて、page1.pug、page2.pugのそれぞれからfooter.pugを読み込む(includeする)ことで、共通部分の管理を楽にすることができます。
includeを使いこなすだけで、複数ページにまたがるWebサイトの構築が圧倒的に楽になります。
includeは
include footer.pug
と記述することで、その記述箇所に、指定のファイルの内容が読み込まれます。page2.pugの例のように、ファイル名指定の際は拡張子.pug
を省略しても問題なくコンパイルすることができます。
また、includeするファイルはincludes
ディレクトリなどにまとめておくことが一般的です。その際には、include
に続けて相対パスでファイルを指定します。
include includes/footer
includeするファイルはpugファイル以外も指定できます。その場合、単純なテキストデータとしてファイルの中身が読み込まれます。
■page1.pug
doctype
html(lang='ja')
head
meta(charset='utf-8')
title Hello, Pug include
body
div.content
p ページ1 コンテンツ
include includes/footer.php
■footer.php
<?php $text="PHPフッター"; ?>
<div class="footer">
<p><?php echo $text; ?></p>
</div>
■page1.html(コンパイル後)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Hello, Pug include</title>
<body>
<div class="content">
<p>ページ1 コンテンツ</p>
<div>
<div class="footer">
<p>PHPフッター</p>
</div>
</body>
</html>
3. extends(継承)
includeだけでもテンプレートエンジンの効力は十分なのですが、extends(継承)を使用するとさらに効率よくWebサイトを構築することが可能です。
まずは以下ファイルを作成しましょう。index.pugと同じ階層にlayoutディレクトリを作り、その中にlayout.pugを作成します。
■layout/layout.pug
doctype html
html
head
meta(charset='utf-8')
block title
body
block content
h1 Default Content
■index.pug
extends layout/layout.pug
block title
title Page Title
block content
h1 Page Content
index.pugファイルをコンパイルすると以下のようになるかと思います。
■index.pug
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Page Title</title>
<body>
<h1>Page Content</h1>
</body>
</html>
先ほどのincludeとの違いが少しわかりづらいかと思います。
以下の図のように、includeでは共通部分をパーツ化していましたが、共通部分が多くなってきた場合、それらをまとめて一つにした方が管理しやすくなります。
その際にextendを使用し、共通部分を一つのファイルにし、ページごとに異なる部分をそれぞれのページで記述する形になります。
■include
■extends
はじめにページのテンプレートとして、layout.pugで基本的な構造を作成します。その中でページごとに変更したい箇所は、block文を使用します。
今回はhead
内のタイトルとbody
内のコンテンツにblock文を使用しました。
block文の書き方は、block
に続いてブロック名を宣言します。
■layout/layout.pug
block title
ここではtitleにしていますが、なんでも構いません。内容に沿ったわかりやすいブロック名がいいでしょう。
index.pug側で、個別のタイトルの内容を作成します。
まず、index.pugではどのファイルをテンプレートとして使用するかを、extends
で指定します。
■index.pug
extends layout/layout.pug
そして、先ほどブロック名を宣言したブロックの内容を定義します。
この時、layout.pugでの宣言時と同じblock文を使用するため紛らわしいのですが、こちらではインデントで区切って内容を定義する必要があります。
■index.pug
block title
title Page Title
block文は初期(デフォルト)値を持つことができます。先出の例ではコンテンツ部分で使用しています。初期値はblock文に続く行に、一つ下のインデントで記述します。
読み込み側(ここではindex.pug)で内容が定義されていないと、初期値が表示されます。
■layout/layout.pug
block content
h1 Default Content
index.pugでblock content
を定義しないと、出力されるHTMLは以下のようになります。
■index.html
<h1>Default Content</h1>
4. mixin(ミックスイン)
最後に、mixinについて説明します。
ここまでの内容で基本的なテンプレートは作成できますが、includeで共通部分を作る際に、ページごとに内容が少しずつ違う場合はどのようにしたらいいでしょうか。
例えばグローバルナビゲーションを共通化した際に、今いるページには印(クラス)をつけたい場合などが当てはまります。
まずはincludeと同じように、全く同じ内容を複数箇所で呼び出してみましょう。
■index.pug
mixin list
ul.gNav
li: a(href='home.html') HOME
li: a(href='about.html') ABOUT
li: a(href='news.html') news
doctype html
html
head
title Hello, Pug Mixins
body
+list
.content ページごとのコンテンツ
+list
■index.html(コンパイル後)
<!DOCTYPE html>
<html>
<head>
<title>Hello, Pug Mixins</title>
</head>
<body>
<ul class="gNav">
<li><a href="home.html">HOME</a></li>
<li><a href="about.html">ABOUT</a></li>
<li><a href="news.html">news</a></li>
</ul>
<div class="content">ページごとのコンテンツ</div>
<ul class="gNav">
<li><a href="home.html">HOME</a></li>
<li><a href="about.html">ABOUT</a></li>
<li><a href="news.html">news</a></li>
</ul>
</body>
</html>
mixin(ミックスイン)は、mixin文に続きmixin名を宣言し、次のインデントで内容を定義します。
mixinを呼び出す時には、+
のすぐ後にmixin名を指定します。
mixinはincludeと異なり、同じファイルに内容を記述することができます。また、mixinをまとめたファイルを新たに作成し、そのファイルをincludeして使うことも可能です。
■mixin/mixin.pug
mixin list
ul.gNav
li: a(href='home.html') HOME
li: a(href='about.html') ABOUT
li: a(href='news.html') NEWS
■index.pug
include mixin/mixin
doctype html
html
head
title Hello, Pug Mixins
body
+list
.content ページごとのコンテンツ
+list
mixinは関数のイメージで考えるとわかりやすいかと思います。
それではページ毎にグローバルナビゲーションの現在のページにクラスをつけてゆきましょう。
■mixin/mixin.pug
- var list = ['home', 'about', 'news']
mixin list(now)
ul.gNav
each item in list
- var name = item.toUpperCase()
if now === item
li.now: a(href=item + '.html') #{name}
else
li: a(href=item + '.html') #{name}
■index.pug
include mixin/mixin
doctype html
html
head
title Hello, Pug Mixins
body
+list('home')
.content ページごとのコンテンツ
+list('home')
■index.html(コンパイル後)
<!DOCTYPE html>
<html>
<head>
<title>Hello, Pug Mixins</title>
</head>
<body>
<ul class="gNav">
<li class="now"><a href="home.html">HOME</a></li>
<li><a href="about.html">ABOUT</a></li>
<li><a href="news.html">NEWS</a></li>
</ul>
<div class="content">ページごとのコンテンツ</div>
<ul class="gNav">
<li class="now"><a href="home.html">HOME</a></li>
<li><a href="about.html">ABOUT</a></li>
<li><a href="news.html">NEWS</a></li>
</ul>
</body>
</html>
コードをスッキリさせるためにeach in
を使用したので少しわかりづらいですが、ポイントはmixin側でも呼び出し側でも新たに括弧の中にパラメータが加えられているところになります。
mixin側では任意の変数名を括弧の中に入れます。
mixin list(now)
呼び出し側では、渡す値を入れます。
+list('home')
これによりlist
mixinにはhome
という文字列が渡され、変数now
の中に格納されます。
変数now
はif文によって評価され、ナビゲーションリストの内容と同じだった場合、li
要素にnow
クラスが付与されるようになっています。
パラメータはJavaScriptの関数と同じように、カンマ区切りで複数やり取りすることが可能です。
■mixin側
mixin list(now, name)
+list('home', 'INDEX')
5. まとめ
以上、Pugでinclude(インクルード)とextends(継承)、mixin(ミックスイン)を使用する方法を紹介してきました。
実際にはこれら3つを組み合わせて、サイトのテンプレートを作成してゆくことになります。
今回はlayout.pugやmixin.pugなど、レイアウトテンプレートやmixinを一つのファイルにまとめましたが、layout-header.pug、layout-footer.pugを作成し、layout.pugでそれらをincludeしたり、mixin-grovNav.pug、mixin-sidebar.pugと複数のmixinファイルを用意し、必要なものだけ読み込んだりして構築してゆくことも可能です。
普段プレーンなHTMLだけでコーディングしていると、extendsやmixinがとても難しく感じますが、一つ一つできるところから取り入れてゆくことで少しずつ効率化してゆくのが良いかと思います。
全てマスターした頃には、プレーンなHTMLだけでコーディングしていた頃より圧倒的なスピードで開発できるようになっているはずです。
コメントを残す