共通部分が多いHTML共通部分が多いHTMLを効率よく作るには、さまざまな手法が考えられます。このシリーズでは、テンプレートエンジンを使用してHTMLを生成するという手法を取り上げ、解説していきます。翔大郎フロントエンド・エンジニア次回このシリーズの記事一覧をみる目次HTMLを作成していてつらいときとは解決するためによくある手法ローカルでHTMLを生成するここまでのまとめピクセルグリッドでは、企業サイトのリニューアル案件やWebアプリケーションのフロント側の制作が主になっています。中でも、リニューアル案件では、ページの量産は行わず、量産のもととなるページのHTMLを作成しています。量産は行いませんが、サイトの規模によっては、それなりの量のHTMLを作成していく必要があります。最近関わった案件ではPC用40ページとSP用40ページ、合計80ページを作成する必要がありました。それらのHTMLには、ヘッダーやフッターであったり、サイドバーであったりと、共通する部分が多く存在します。筆者はその80ページを1ページ毎に、一からHTMLを書くことはしませんでした。HandlebarsというHTMLテンプレートエンジンを使用したのです。Handlebarsでは、共通部分を別のファイルに切り出し、それらを各ページで使用することで、すべてのページに同じHTMLが記述されます。その共通部分に修正があったときには、その切り出したファイルを修正すればすべてのHTMLに反映されるようにしました。これが筆者の言う「一からHTMLを書くことはしない」ということになります。昔の私であれば、共通部分をコピペして1ページ1ページ作成していましたし、共通部分に修正があった場合は、すべてのHTMLに対して置換を行っていました。上述したように、今はHTMLテンプレートエンジンを利用することでその手間を減らすことができています。本記事では、こういった「できるだけHTMLを書かない・書く量を減らすための手法」を紹介します。注:テンプレートエンジンJavaScriptからテンプレートエンジンを扱う方法については、CodeGridで過去に記事として取り上げています。テンプレートエンジンのススメHTMLを作成していてつらいときとは筆者がHTMLを書いていてつらいと感じるときは、つぎのような場合です。ほとんど同じような内容なのに、1ページ1ページ丁寧にHTMLを作らなくてはいけない1箇所変更があったら、全ページを修正することもあり、変更漏れや置換ミスが起こるHTMLが複雑になっていき、閉じタグの位置がわかりづらくなり、閉じタグが欠落するHTML自体にはプログラミング言語でいう変数やfor文などの仕組みがないため、同じような記述を何度もしなくてはいけません。閉じタグが欠落していたとしても、ブラウザはよしなに補完し、ある程度の見た目で表示されます。バリデーションしていれば、閉じタグがないといったことに気付くことはできます。閉じタグを書かずにHTMLを作成することができれば、閉じタグが欠落するといったミスをなくすことができるかもしれません。効率的にHTMLを作成するためにはどのような方法があるかを挙げてみます。似たようなページを大量に作る場合や、大量に作ったページすべてに修正があった場合などに、制作を楽にする方法としてよく利用される「インクルード」というものがあります。ファイルの中に別のファイルを組み込むインクルードインクルードは、ファイルの中に別のファイルを組み込むことを指します。ヘッダーやフッターといった共通部分のHTMLを別々のインクルードファイルに分け、その分けたファイルを各ページで読み込むようにし、最終的にHTMLを生成すると、ひとつにまとまって表示されます。しておけば共通部分に変更があったときに、そのインクルードファイルを修正すれば、それらが読み込まれているすべてのページに反映することができます。HTML自身には異なるHTMLファイルをインクルードする機能がありません。インクルードするためには、ほかにもいろいろな手段があります。筆者が、過去にその問題を解決するために使用した手段を紹介します。iframe要素を使用したインクルードiframe要素を使用すれば、異なるHTMLファイルを表示することができます。iframe要素は異なるHTMLをiframe要素の枠の中に表示しているだけで、インクルードファイルのHTMLの記述が、それをインクルードしているHTMLの記述として挿入されるわけではありません。iframe要素によるインクルードは、ブログパーツや広告の挿入でよく使われています。Include)です。SSIはWebサーバーの機能の一つです。HTML内にサーバーで実行するコマンドを記述し、その結果を画面に反映します。SSIに対応したWebサーバーであれば、HTML中にSSIを記述することができます。ヘッダーのみの記述があるHTMLファイル(header.html)を作成します。-->そして、このheader.htmlが、index.htmlで表示されるようにしたい場合は、以下のようにします。ここはトップページです。(index.html)</div>このindex.htmlを、SSIが動作するサーバー上に置くことで、ブラウザに表示されるHTMLは、次のようになります。ここはトップページです。(index.html)</div>SSIを使用することで、共通する部分を別のファイルにして管理できるので、多少なりともHTMLの作成が楽になります。SSIを利用するためには、サーバーの設定ファイルを変更する必要がありますし、場合によっては使用できないこともあります。サーバー側の負荷や、セキュリティ面で問題があることもあるので、使用する際は、サーバー側の都合と相談して使用したほうがよいと考えます。JavaScriptを使用したインクルード次に、JavaScriptを使用したインクルードです。手段はいろいろありますが、古くからある方法では以下のような形です。ここはindex.htmlです。</div>広告や計測用の挿入タグが、こういった手法をとっていることが多くあります。document.write()以外にも、XMLHttpRequestを使用しHTMLファイルを取得して、その内容を挿入するという方法もあります。注意すべきこととしては、JavaScriptが無効なときに何も表示されないことや、場合によっては表示が遅くなることもあるので、使用する際はいろいろと工夫しなくてはいけないことでしょう。サーバーサイドでテンプレートエンジンを使うまた、サーバーサイドでテンプレートエンジンを使うこともできます。筆者は、Smartyという、PHPで利用できるテンプレートエンジンを使用しました。Smartyでは、サーバーサイドで動的にHTMLを出力します。Smartyのテンプレートでは、SSIのように共通部分を分離したりすることもできますし、インクルードに値を渡すこともできます。class="header">{$text}</div>Smarty用のインクルードファイルであるheader.tplでは$textという値を表示するようにしておきます。ここはindex.htmlです。</div>index.tplでは、header.tplに対して、text='ヘッダー'という形でインクルードファイルに値を渡しています。これがSmartyによって処理されると最終的には次のようなHTMLになります。ここはindex.htmlです。</div>上記のSmartyのファイルを動作させるための実際のコードは、今回の本筋とそれるため省略します。Smartyを使う場合には、サーバー側の環境設定や設計に大きく関係してくること、作業者のローカルで動作させるための準備が多くなることが考えられるため、手軽に導入できるものではないと、筆者は思います。ここまで紹介した手段のどれかを使ったことがある方もいるでしょう。どれも最終的にブラウザで表示されたときに、それぞれのインクルードが展開されます。「サーバーの都合でSSIが使えない」「サーバー側のテンプレートエンジンが使えない」「納品はSSIなどを使わないHTMLでほしい」といった場合にはこれらの手段は使えず、1ページ1ページHTMLを作らなくてはいけません。ローカルでHTMLを生成するこのように、筆者がこれまで利用してきた手段には、いろいろな制限がある場合があります。納品自体は静的なHTMLファイルにする必要があるが、SSIなどが使えない。共通した部分はうまいこと管理したい。いったときには、HandlebarsやECT、Jadeといったテンプレートエンジンを使用してHTMLを生成すると、作業の効率化が図れるかもしれません。これは、Sassのように変数を使ったりファイルを分割したりといったことをHTMLでも行うイメージです。具体的な手法を解説していく前に、これから紹介するどのテンプレートエンジンにも共通した考えを解説しましょう。それはインクルードとテンプレートの継承です。静的なHTMLを生成する時のインクルード前述のとおり、インクルードは共通部分を別ファイルにして、ページごとに読み込む方法です。SSIやSmartyと、ローカルでテンプレートエンジンを使用することの違いは、サーバー側で動的にHTMLを生成するか、それとも静的なHTMLを生成するか、という生成するタイミングの違いになります。各HTMLで共通部分のファイルを読み込み、それらが展開されたHTMLを生成するSSIのようにヘッダとフッタの内容を別ファイルに分け、それぞれのページではその分けたファイルを読み込むことを記述しておきます。最終的にHTMLを生成すると、それらの内容が展開された状態のHTMLを作ることができます。次に、テンプレートの継承です。継承と聞くと難しそうに思えますが、要は、そのサイトで共通で使われる要素の入った雛形です。その雛形の中には、子のテンプレート(雛形を継承するテンプレート)から、上書きや挿入ができるブロックを定義することができます。雛形を利用(継承)して、HTMLを生成する各ページのHTML(図中のsrc/page1.htmlやpage2.html)では、雛形にどのHTMLを使うかを指定します。共通する部分は雛形のHTML(src/partial/layout.html)に書いておきます。テンプレートの継承では、上書きだけでなく、そのブロック内の冒頭に追記する方法や、末尾に追加する方法もあります。雛形の特定箇所を変更して、HTMLを生成するこの図では、layout.htmlにheadとbodyというブロックを用意してあります。それぞれのブロック内には、継承されるページすべてに記述されるコードが書いてあるとします。そのlayout.htmlを継承するpage1.htmlでは、bodyブロックを上書きします。page2.htmlでは、headブロックにprepend、つまり先頭に挿入したいコードを記述します。bodyブロックにappend、つまり末尾に挿入したいコードを記述します。することで、同じ雛形を使いつつ、ページによって異なる記述をすることができます。最終的にHTMLを生成すると、雛形に各ページの内容が反映された状態のHTMLが生成されます(htdocs/page1.htmlとhtdocs/page2.html)。次回から紹介するテンプレートエンジンでは、こういった形で、各ページから雛形の特定の箇所を上書きしたり、その箇所の先頭に追加、末尾に追加するといったことができます。特定のページだけCSSを<head>の末尾に追加するということに使います。インクルードの機能のみでは、必要なページすべてにインクルードの記述を書く必要がありますが、テンプレートの継承ができると継承元のテンプレートに必要なインクルードを記述するだけでよくなり、HTMLの管理がしやすくなるのです。ここまでのまとめ今回は、HTMLを分割して作っていくために過去に筆者がとった手段と、テンプレートエンジンを使用してHTMLを生成するための基礎知識的な部分にフォーカスしました。SSIやJavaScriptによるインクルードといった手段を使うこともあるかもしれません。場合によってはそれらが使用できないこともあります。いったときにも、効率よく制作していくために、テンプレートエンジンを使用してHTMLを生成するという方法も考えられます。次回は、インクルードやテンプレートの継承といった機能を持ったテンプレートエンジンの中でも、筆者が利用したことのある、Handlebars、ECT、Jadeというテンプレートエンジンのそれぞれの特徴と、gulpを使用したHTML生成の方法について解説していきます。翔大郎フロントエンド・エンジニア大手ソフトウェアダウンロード販売会社、Web制作会社などで、マークアップエンジニア、プログラマ、サービス企画、ディレクターを経験。2013年、株式会社ピクセルグリッドに入社。HTML、CSS、JavaScriptなどをオールラウンドに担当。プログラマブルなCSSの設計、実装を得意とする。PANIC」は、JavaScriptを一切使わず、HTMLとCSSのみで実装。海外サイトで紹介されるなど話題となった。特定商取引法に基づく。