PugでHTMLコーディングを効率化・メリットと使い方を知る

画像

古いサイトのヘッダー改修で全ページを修正したり、微妙にことなるHTMLを繰り返し大量に書いたり(エディタがどんどん重くなる)、閉じタグ忘れを血眼になって探したことはないだろうか。

EmmetSassでコーディングはかなり楽になったけれど、僕の作業を一番効率化してくれたのは、同時期に覚えたPugという技術だった。ここでは、Pugの概要とメリットを簡単に紹介したい。

Pugとは

Pug(パグ)は、HTMLを効率的に書くためのテンプレートエンジン。使い方はCSSで言うSassみたいなもの。拡張子 .pug のファイルを書いてHTMLに変換する。

もともとはJade(ジェード)という名前で開発されていたものの、商標の関係で2016年あたりにPugとして再リリースされた。新しいPug(2018年3月12日現在v2.0.1)は繰り返しや属性などの書き方が若干変更されている。Jadeのコードを流用する場合は記法変更によるエラーに注意。

ちなみに、Vue.jsのテンプレートをPugで書くこともできるので、記法を覚えておいて損はない。

Pugの記法

Rubyのようにインデントのみで階層化を行い書いていくのが基本。

main#main
  ul.btns
    li
      a.btn(href="/") ボタン

<main id="main">
  <ul class="btns">
    <li><a href="/" class="btn">ボタン</a></li>
  </ul>
</main>

コンパイルが必要

Pugはブラウザで認識されないので、普通のHTMLを書きだす(コンパイル)仕組みを作る。コンパイルは、タスクランナー系(gulpなど)やコンパイラーアプリ(Preprosなど)を用いて自動化するのが一般的。

Pugのメリット

ここでは、僕が便利になったと感じている特徴をリストアップしてみる。

閉じタグ忘れがなくなる

自動的に閉じタグが生成されるので、閉じタグ忘れが100%なくなった。Emmetを使い出して軽減できていたものの、修正しているうちに閉じタグ数がずれることもあったので。

書き方をCSSと統一できる

classは .、idだと # で書くのでCSSとの連携が取りやすい。

ファイルを分割管理できる

Sassと同じく別ファイルを読み込んで書き出せるのが便利。静的ページの共通ヘッダー・フッター修正も楽勝。以下では _header.pug_footer.pug を別ファイルで作っていた場合を想定。

include section/_header.pug

main#main
  ul.btns
    li
      a.btn(href="/") ボタン

include section/_footer.pug

<header>
  <h1>
    <a href="#"><img src="img/logo.svg" alt="Pugの説明ページ|Pugの説明サイト" class="logo"></a>
  </h1>
</header>
<main id="main">
  <ul class="btns">
    <li><a href="/" class="btn">ボタン</a></li>
  </ul>
</main>
<footer>
  <p class="copylight">&copy; 運営会社名</p>
</footer>

変数で修正が楽になる

JavaScriptのように変数が使えるので、「サイト名が変更になりました。お手数ですが全ページ修正いただけますか」というありがちな無茶振りを楽に捌ける。変数を格納するファイルを別に作っておいて、全ページで最初に読むと楽。

- var title = "Pug(Jade)の説明ページ|色々と説明するサイト";

doctype html
html(lang="ja")
  head
    meta(charset="UTF-8")
    title #{title}
  body
    header
      h1
        a(href="#")
          img.logo(src="img/logo.svg" alt=title)

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Pug(Jade)の説明ページ|色々と説明するサイト</title>
</head>
<body>
  <header>
    <h1>
      <a href="#"><img src="img/logo.svg" alt="Pug(Jade)の説明ページ|色々と説明するサイト" class="logo"></a>
    </h1>
  </header>
</body>
</html>

条件分岐を作れる

例えば、トップだけ h1 にして他のページは p にするなどの条件分岐が可能。

- var page = "index";

case page
  when "index"
    h1 タイトル
  default
    p タイトル

<h1>タイトル</h1>

繰り返しを楽に書ける

「同じ書き方だけどテキストと画像だけ変えていく」みたいな繰り返し作業はHTMLだとコピペ修正地獄となり苦しい。Pugでは each を使うことでとても簡単に処理できる。

ul
  each val in [1, 2, 3, 4, 5]
    li= val

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>

変数を入れ子にしてデータベース化することで柔軟な制作が可能。

-
  var nav = {
    index : {
      title : "HOME",
      url : "/"
    },
    about : {
      title : "ABOUT",
      url : "about.html"
    },
    works : {
      title : "WORKS",
      url : "works.html"
    },
    /*service : {
      title : "SERVICE",
      url : "service.html"
    },*/
    contact : {
      title : "CONTACT",
      url : "contact.html"
    }
  }

nav.nav.is-global
  each val in nav
    a.nav-item(href=val.url)
      span.text= val.title

<nav class="nav is-global">
  <a class="nav-item" href="/"><span class="text">HOME</span></a>
  <a class="nav-item" href="about.html"><span class="text">ABOUT</span></a>
  <a class="nav-item" href="works.html"><span class="text">WORKS</span></a>
  <a class="nav-item" href="contact.html"><span class="text">CONTACT</span></a>
</nav>

mixin

Sassと同じようにmixinが使える。書き方は + を使って呼び出すようになっている。

mixin pet(name)
  li.pet= name

ul
  +pet('cat')
  +pet('dog')
  +pet('pig')

<ul>
  <li class="pet">cat</li>
  <li class="pet">dog</li>
  <li class="pet">pig</li>
</ul>

Markdown(npmライブラリ必須)

npmライブラリの jstransformer-markdown-it を併用することでPugの中でMarkdownが使えるようになる。残念ながらPreprosではこの手法が使えない。

.wysiwyg
  :markdown-it
    ## ソースコード

    まずはローカルで読み込む。

<div class="wysiwyg">
  <h2>ソースコード</h2>
  <p>まずはローカルで読み込む。</p>
</div>

やりすぎ注意

HTMLを条件分岐・ファイル分割するのは楽しいので凝ってしまいがち。あまりに複雑な組み方にしてしまうと、引き継ぎはもとより自分でも思い出せなくなってしまう。

条件分岐は発生するルールを決め、ファイル分割はAtomic Designを意識して「ページ・セクション・モジュール」の3階層と決めると安定する。

参考

自分が作っているライブラリのデモサイトはだいたいPugで書いているので、具体的な書き方を知りたい場合は参考にしてほしい。