静的サイトジェネレーターEleventy 第1回 Eleventyとその特徴
ビルドにより静的サイトを生成するツール、Eleventyの使い方を解説します。まずはほかの静的サイトジェネレーターとどう違うのか、その特徴を整理します。
- カテゴリー
- Jamstack >
- 静的サイトジェネレーター
発行
はじめに
静的サイトジェネレーターは、ビルドによりWebサイトを生成するツールです。単純な静的Webサイトを生成する場合には特に便利ですが、Jamstack構成*での動的なWebサイトを生成するのにも使われます。
*注:Jamstack
Jamstackは、サーバーサイドも含めたWeb開発全体のアーキテクチャです。CodeGridでもJamstackを解説したシリーズがありますので、参考にしてください。
Jamstackというと、Reactを利用したGatsbyや、Vue.jsを利用したNuxtのようなSPA開発のライブラリを利用したものが話題になりがちですが、必ずしもそういったライブラリが必要なわけではありません。GitHubで採用され、今も開発が続くJekyllのように、もっとシンプルに静的サイトを生成するツールもあります。
今回紹介するEleventyもそういったシンプルなツールの一つです。ほかの静的サイトジェネレーターとどう違うのか、ということも含めてみていきましょう。
Eleventyができること
Eleventyは最初に説明したとおり、Webアプリケーションというより、Webサイトを生成するのに向いているツールです。
多くのテンプレート形式に対応している特徴があります。
- HTML(.html)
- Markdown(.md)
- JavaScript(.11ty.js)
- Liquid(.liquid)
- Nunjucks(.njk)
- Handlebars(.hbs)
- Mustache(.mustache)
- EJS(.ejs)
- Haml(.haml)
- Pug(.pug)
- JavaScript Template Literals(.jstl)
*注:.11ty.js
という拡張子
.11ty.js
は通常のJavaScriptと、Eleventyが使うテンプレート言語としてのJavaScriptと区別するために付けられているものです。.11ty
の部分は正確に言うと拡張子ではなく、ファイル名の一部です。
かなりの種類に対応していますが、Reactで使うJSXやvueファイルなどはありません。
主に次のようなことができます。
- MarkdownファイルからのHTMLページ生成
- 複数のテンプレート形式を使い分けてHTMLページ生成
- ページの継承、インクルードといったHTMLのコンポーネント管理
- ページ生成に必要なデータをJSONなどのテキストファイルから読み込み
- APIから非同期でデータの取得
- あらゆるテキスト形式のファイル生成
データとAPIを組み合わせてのWebサイトの生成が得意で、複数テンプレートに対応していることで、ほかの静的サイトジェネレーターからの移行にも強いでしょう。
しかし、次のようなことは基本的には面倒をみてくれません(テキスト形式のファイル生成の一部としては可能です)。
- CSSのスコープ管理・コンポーネント管理
- ブラウザ側でのJavaScriptの依存解決・バンドル
- CSSやJavaScriptのminify
CSSやJavaScriptをコンポーネントとして管理してくれる機能はないので、ページで使われているCSSやJavaScriptをどう依存解決していくかといったことは、Eleventyの外側で別途考える必要があります。
JavaScriptフレームワークベースにはない利点
Eleventyの利点としてまず言えるのは、JavaScriptフレームワークの知識がない人でも扱いやすいことでしょう。テンプレートエンジンベースになるので、WordPressなどのCMSを扱ってきた人はすんなり扱えそうです。また、HTMLとCSSを書くHTMLコーダーの人が効率化するための次のステップとしてもよさそうです。
最近のReactやNuxtといったSPA系フレームワークに慣れていると、昔に戻ったと感じるかもしれません。しかし、実際にはテキストベースであることで、ブラウザに搭載された新しい技術への対応はしやすくなっています。特にWeb Componentsと組み合わせる場合は扱いやすいでしょう。
Web ComponentsとJavaScriptフレームワーク
Web Componentsという標準仕様があります。その中のcustom elementsという機能では、独自のHTML要素を作ることができます。
こういった、標準技術はJavaScriptフレームワークでそのまま使えない場合も多く、実際にNuxtで試したときにはVueのコンポーネントと間違ってエラーが出るので、設定をして対応しました。うまく動かした後でも、DOM操作が行われる前提のWeb ComponentsとVirtualDOMは相性が悪く、さまざまな苦労をすることになります。
さらに、JavaScriptフレームワークに依存していないということは、クライアント側で使うJavaScriptを好きに選べるということでもあります。「基本的にはVue.jsを使うけど、以前から運用してるこのページはjQueryのままにする」といったこともできます。
全体の統一という点では問題があるかもしれませんが、自由度の高さという意味でJavaScriptのフレームワークに依存してないのは大きな利点です。
Eleventyでサイトを生成する
さて、いろいろ説明してきましたが、まずは簡単に動かしてみましょう。Node.jsが入っていればEleventyは簡単に使うことができます。
Eleventyのインストール
以下のコマンドでグローバルにインストールすると、どこでもeleventy
というコマンドが使えるようになります。
$ npm install -g @11ty/eleventy
プロジェクトで使う場合、他の人とバージョンを合わせたり、グローバルにインストールが必要ないように、ローカルにインストールすることが多いでしょう。
$ npm install --save-dev @11ty/eleventy
プロジェクトのディレクトリにpackage.jsonを作ります(なければnpm init --yes
、またはnpm init -y
で作成できます)。ローカルインストールの場合は、eleventyコマンドを直接実行できないので、package.jsonのscriptsにeleventyを実行するコマンドを足しておきましょう。最小限のpackage.jsonはこのような感じです。
package.json
{
"private": true,
"scripts": {
"build": "eleventy"
},
"devDependencies": {
"@11ty/eleventy": "^0.9.0"
}
}
変換するファイルを用意する
次にMarkdownからHTMLを生成する想定で、Markdownファイルを用意しましょう。
デフォルトでは変換する元のファイルはeleventy
コマンドを実行した場所以下にある、すべての対応する拡張子のファイルになりますので、ファイルはpackage.jsonファイルと同じフォルダに入れておけば良いでしょう。ここではindex.md
という名前で作成しました。
index.md
# 見出し
本文
サイトの生成
用意できたら、さっそくHTMLの生成を実行してみます。npm run build
を実行します。
$ npm run build
> @ build /Users/kyosuke/my-11ty-project
> eleventy
Writing _site/index.html from ./index.md.
Processed 1 file in 0.09 seconds (v0.9.0)
これだけで、_siteというフォルダが作成され、その中にindex.htmlが生成されているはずです。
中身を見てみましょう。
_site/index.html
<h1>見出し</h1>
<p>本文</p>
……確かに、mdファイルを元にHTMLが生成されていますが、本当にmdファイルをHTMLにしただけのものです。余計なことをしないのは素晴らしいですが、title要素もないテキストファイルをHTMLと言っていいのか突っ込みたい人もいるでしょう(少なくとも筆者はそう思いました)。
テンプレートを継承して生成
もう少し真っ当なHTMLになるよう、テンプレートを用意します。最初に説明したようにEleventyではさまざまなテンプレートに対応していますが、今回はEleventyのドキュメントの例としてもっとも多く載っているNunjucksで用意します。
といってもテンプレート特有の部分はコンテンツが挿入される{{ content | safe }}
だけです。用意したファイルは、_includesという名前のフォルダを作り、その中に入れます。
_includes/layout.njk
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>サイト名</title>
</head>
<body>
{{ content | safe }}
</body>
</html>
index.mdファイルの方では、このテンプレートを継承して生成するようfront-matterで設定をします。mdファイルの先頭に---
で囲まれたテキストを追加し、このように書きます(YAML形式です)。
index.md
---
layout: layout.njk
---
# 見出し
本文
これで再度HTMLの生成npm run build
を実行してみましょう。先ほどと同じようにindex.htmlが生成、更新されて次のようになるはずです。
_site/index.html
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>サイト名</title>
</head>
<body>
<h1>見出し</h1>
<p>本文</p>
</body>
</html>
先ほどmdファイルがそのまま変換されていたHTMLが、{{ content | safe }}
の代わりに出力されました。この仕組みだけでも、mdファイルを自由な形でHTMLファイルにできることがわかります。
サーバーの起動
テンプレートを変更するたびにbuildを実行するのは面倒です。eleventyコマンドはオプションをつけると、開発用のサーバーを起動し、テンプレートの変更を監視してくれます。
$ eleventy --serve
こちらもpackage.jsonに足しておきましょう。これで、npm run serve
で実行できます。
package.json
"scripts": {
"build": "eleventy",
"serve": "eleventy --serve"
},
実行後に表示されるURLにアクセスすると、テンプレートが表示されていることがわかります。
BrowserSyncによるサーバーですので、元のmdファイルなどを編集して保存するたびに自動でブラウザがリロードされます。複数ブラウザを同時に開いての確認などでも便利です。
BrowserSyncについては、CodeGridではnpm scriptから使う方法やgulpの設定方法を紹介してますが*、Eleventyの場合はなにも設定せずに利用することができます。
*注:npm scriptsでビルドする方法やgulpの設定方法
まとめ
今回はEleventyの概要とMarkdownファイルからHTMLを生成する流れを紹介しました。次回はfront-matterのデータを使う方法と、テンプレートファイルの配置と出力ファイルの対応について解説する予定です。