owned mediaウェブ制作に役立つコンテンツを発信中!

Pugでページテンプレートの作成にextendsとblockを活用する

最終更新日: Update!!
PugはJavaScriptのテンプレートエンジンで、HTMLを効率よくコーディングすることができます。Nuxt.jsなどのフレームワークの中でも使うことができ、個人的にも案件で触る機会が多いのでとても役立っています。   Pugにはいろんな機能が用意されているのですが、その中でも「extends」と「block」は少し馴染みがなくとっつきにくいイメージがあるのではないでしょうか。そこで今回は、この2つを使ってページテンプレートを作成する例をまとめていきたいと思います。   今回はこのようなファイルおよびフォルダ構成になっています。componentsフォルダの中には、ヘッダーとフッター部分のパーツと、ページ全体の大枠となる3つのコンポーネントを作成しています。そして、ページ固有のコンテンツエリアをページテンプレートのベースとして必要なページ分用意する形となります。
┣ components
  ┣ _layout.pug
  ┣ _header.pug
  ┗ _footer.pug
┣ index.pug
┣ page-01.pug
┣ page-02.pug
  ..............
 
インクルードさせるときに使うincludeとblockについて
Pugファイルには外部からインクルードさせる方法として2つの機能があります。よく似ているのですが使う目的が異なりますので、うまく使い分けることが重要です。まずはこちらを理解する必要があります。  
include 継承元のPugファイルの中で指定されたPugファイル全体をそのままインクルードさせる、半角スペースを挟んで、対象のPugファイルのパスを指定することで呼び出す
block 継承元のPugファイルの中で特定の一部のエリアのみインクルードさせる、変数として定義して、その変数を指定することで呼び出す
  いまいち違いがわかりにくいかもしれませんが、実際のユースケースを見るとイメージしやすいと思います。下記にコンポーネントとして使う3つのPugファイルを作成します。まずは共通部分であるヘッダーとフッターです。 【_header.pug】
header
  h1 ヘッダーエリアです
  【_footer.pug】
footer
  h1 フッターエリアです
  今回はサンプルですので非常にシンプルですが実際にはデザインに応じて、このPugファイル内でそれぞれ作り込まれていきます。続いてページの大枠となる部分です。 【_layout.pug】
doctype html
html(lang="ja")
  head
    meta(charset="utf-8")
    meta(name="viewport" content="width=device-width,initial-scale=1.0")
    link(rel="stylesheet" href="main.css")
  body
    include ../components/_header.pug
    block pageContent
    include ../components/_footer.pug
  まずはページ全体の大枠となる部分ですが、この中では共通部分であるヘッダーとフッターのPugファイルで出来たコンポーネントをincludeで呼び出しています。こうすることで、ページの大枠の中にヘッダーとフッターが配置された形のようになります。そして、ページのコンテンツ部分はblockで呼び出しています。blockについては後述でも説明しますが、この後紹介するextendsと呼ばれる機能を使って継承元と継承先によって振る舞いが異なります。   ここでページコンテンツ部分をincludeではなくblockとして呼び出しているのは、ページのレイアウトや導線が変更となった場合に、粒度を細かくしておくことで柔軟に対応できるようにするためになります。なぜblockとするとメンテナンス性が上がるかという理由は、次のextendsの機能を理解することではっきりとしてきます。  
特定のPugファイルを継承するextends
extendsを使うことで、特定のPugファイル内で指定したPugファイルの内容を継承することができます。継承するというとわかりにくいかもしれませんが、継承元のPugファイルをそのまま使い、その中に内容を追加していけるようなイメージになります。  
extends 指定のPugファイルをベースとして引き継ぐことができる、半角スペースを挟んで、継承元のPugファイルを指定する。継承すると継承元のPugファイルの中に組み込まれたような形になる。
block 継承元で呼び出されたときに表示する内容を定義する。半角スペースを挟んで、変数名を定義し、改行を行いインデントを入れて、続けて呼び出される内容となるHTMLを定義していく。
  先ほどは継承元で、blockをインクルードさせる対象として呼び出しに使っていましたが、継承先では呼び出される内容を定義する形になります。どちらも同じblockという名前で使うので少しややこしい点に気をつけましょう。   今回の例では、全体のレイアウトの大枠をコンポーネント化したPugファイルとして作成し、それをページごとのPugファイルでextendsさせることにより、全体の大枠もテンプレート化するという目的があります。ここではトップページのページテンプレートとなるPugファイルで見ていきましょう。 【index.pug】
extends components/_layout.pug
block pageContent
 main
 p トップページのコンテンツエリアです
  extendsでヘッダーとフッターがインクルードされたページ大枠部分のテンプレートを継承します。こうすることで、ページテンプレートが大枠部分に組み込まれたような形で利用することができます。そして、コンテンツ部分にはそれぞれのページに合わせた内容をblockとして表示させる形になります。その際には呼び出す場合の識別子となる変数名を定義し、改行とインデントを入れてからコンテンツ部分を定義します。   ここで定義したblockは、先述のページ大枠部分のコンポーネントで、呼び出している形になりますので、ページテンプレートごとにコンテンツ部分だけをPugファイルとして切り出すことができます。もちろん1つのPugファイルに複数のblockを定義することも可能です。   これで実際にextendsとblockを使ったPugファイルをHTMLへとコンパイルしていきます。確認してみますと、きちんと予定通りのHTMLが出来上がっているのがわかりますね。 【index.html】
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="stylesheet" href="main.css">
  </head>
  <body>
    <header>
      <h1>ヘッダーエリアです</h1>
    </header>
    <main>
      <p>トップページのコンテンツエリアです</p>
    </main>
    <footer>
      <h1>フッターエリアです</h1>
    </footer>
  </body>
</html>
  なお、extendsを使ったコーディングをしているとこのようなエラーに出くわすこともあります。
Declaration of template inheritance ("extends") should be the first thing in the file. There can only be one extends statement per file.
  これは、ファイルの先頭以外にextendsを定義していることで発生するエラーです。ファイルの先頭以外にextendsを記述している、あるいは複数のextendsを指定しているなどが原因であると考えられます。ですので1つのPugファイルに指定できるextendsは1つだけということになります。これはextendsの性質を見ると当然であると言えますね。   このように、extendsを使うことで細かいコンポーネントをincludeさせる場合と比較しても、より効率よく少ないPugファイルでコンポーネント化させることができます。ただし今回の場合ですと、extendsしているページ大枠内に、タイトルやSEOのメタ要素などページ固有の情報を入れることができない状況です。  
  今回触れたのは、extendsとblockの基本的な部分になります。そこでまた次回の記事で、blockにページ固有の情報をまとめて変数化させることで、共通パーツ内でページごとに異なる内容に切り替えられる方法についてまとめていきたいと思います。
  • はてなブックマーク
  • Pocket
  • Linkedin
  • Feedly

この記事を書いた人

Twitter

sponserd

    keyword search

    recent posts

    • Twitter
    • Github
    contact usscroll to top
      • Facebook
      • Twitter
      • Github
      • Instagram