この記事はJamstack Advent Calendar 2020の8日目の記事です。
はじめに
SSGといえば、東京都 新型コロナウイルス感染症対策サイトで使われているVue製のNuxt.jsやReact製のGatsbyやNextが有名です。
しかし、VueやReactで書かなければいけないので、Web初学者からすると敷居が高くなかなか手が出しづらいと思います。
一方、11ty/eleventyの基本はHTML(テンプレートエンジン)なので、多少テンプレートエンジンの文法を覚える必要はありますが、
VueやReactと比較すると学習コストは低いと思いますので手を出しやすいかと思います。
11ty/eleventy とは
- 11ty/eleventyは**zachleat**氏によって制作さいれている静的サイトジェネレーター(SSG)
- テンプレートエンジンの詰め合わせのようなもの
- デフォルトで以下の言語に対応しています。
- HTML(.html)
- Liquid(.liquid)
- EJS(.ejs)
- Markdown(.md)
- Handlebars(.hbs)
- Mustache(.mustache)
- Haml(.haml)
- Pug(.pug)
- Nunjucks(.njk)
- JavaScript(.11ty.js)
- デフォルトで以下の言語に対応しています。
- 今回は利用しませんが、ローカル開発用のサーバも組み込まれています。
事前準備
また、microCMSへのデータの投入は済ませておいてください。
(今回はこちらの記事で用意したゴリラたちデータを利用します。)
方針
- 11tyはHTMLのコンパイラとして利用する
- 全体のワークフローはnpm scriptsで実行する
- 11tyをメインにすると、他のワークフローが組み込みにくいため...
- テンプレートエンジンは
Handlebars
を利用する- npm trendsで見てみても割と人気なため
ディレクトリ構成
root/
├ dist/ ・・・ 出力ディレクトリ
├ src/ ・・・ 入力ディレクトリ
│ ├ components/ ・・・ パーツ配置ディレクトリ
│ │ └ row.hbs
│ ├ data/ ・・・ データ配置ディレクトリ
│ │ └ gorillas.js
│ ├ layouts/ ・・・ レイアウト配置ディレクトリ
│ │ └ default.hbs
│ └ pages/ ・・・ エントリポイント配置ディレクトリ
│ └ index.hbs
├ .bs-config.js ・・・ BrowserSync設定ファイル
├ .eleventy.js ・・・ eleventy設定ファイル
└ package.json
プロジェクトの作成
console
# nodeのバージョン確認
% node -v
v14.0.0
# npm のバージョン確認
% npm -v
6.14.9
# プロジェクトの初期化
% npm init -y
% npm i -D @11ty/eleventy
# 11tyにも含まれていますが、今回は11tyをただのビルダーとして使いたかったため、別途インストール。
% npm i -D browser-sync
# npm-scriptsでタスクの直列、並列実行するため。
% npm i -D npm-run-all
# CLIからファイルの削除を行うため。
% npm i -D rimraf
# microCMSからデータを取得するために利用
% npm i -D node-fetch
各種設定ファイルの作成
package.json
{
// scriptsに追記する
"scripts": {
"build": "run-s clean build::*",
"build::html": "eleventy",
// "build::css"などを作ってdistフォルダへ出力ようにすればsassなども利用できます。
"clean": "rimraf dist",
"server": "browser-sync start --config \"./.bs-config.js\"",
"start": "run-p watch server",
"watch": "run-p watch::*",
"watch::html": "eleventy --watch"
// "watch::css"などを作ってdistフォルダへ出力ようにすればsassなども利用できます。
}
}
.bs-config.js
/**
* Browser-sync Configuration
*/
module.exports = {
ui: false,
server: "dist",
ghostMode: false,
open: false,
notify: false,
};
.eleventy.js
/**
* Eleventy Configuration
*/
module.exports = (eleventyConfig) => {
return {
dir: {
// 入力ディレクトリ
// input: ".",
input: "src/pages",
// インクルードのディレクトリ
// includes: "_includes",
includes: "../components",
// レイアウトのディレクトリ
// layouts: "_includes",
layouts: "../layouts",
// グローバルデータファイルのディレクトリ
// data: "_data",
data: "../data",
// 出力ディレクトリ
// output: "_site",
output: "dist",
// グローバルデータファイルのデフォルトのテンプレートエンジン
dataTemplateEngine: false,
// マークダウンファイルのデフォルトのテンプレートエンジン
markdownTemplateEngine: "liquid",
// HTMLファイルのデフォルトのテンプレートエンジン
htmlTemplateEngine: "liquid",
// テンプレートフォーマット
templateFormats: [
// "html",
// "liquid",
// "ejs",
// "md",
"hbs",
// "mustache",
// "haml",
// "pug",
// "njk",
// "11ty.js",
],
},
};
};
環境の動作確認コマンド
# ビルドの実行
% npm run build
# 開発サーバの起動
% npm run start
microCMSからデータ取得
src/data/gorillas.js
const fetch = require("node-fetch");
module.exports = async () => {
const res = await fetch("https://jamstack-sample.microcms.io/api/v1/gorilla", {
headers: {
// microCMSから取得したAPIキーを設定
"X-API-KEY": "XXXXXXXXXXXXXXXXXXXX",
},
});
return items;
};
データを表示するテンプレートを作成
ページ共通のレイアウト
src/layouts/default.hbs
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="index, follow">
<title>{{title}}</title>
<meta name="description" content="{{description}}">
<!--アイコンの設定-->
<link rel="icon" href="/favicon.ico">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<!--その他設定-->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="format-detection" content="telephone=no,address=no,email=no">
<meta name="theme-color" content="#fafafa">
<!--外部ファイルの読み込み-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/destyle.css@2.0.2/destyle.css">
</head>
<body>{{{content}}}</body>
</html>
```
`{{title}}`や`{{description}}`は、この後作成するページ側のhbsファイルより[front-matter](https://www.npmjs.com/package/front-matter)を使って投入します。
### ページのコンテンツ
```html:src/pages/index.hbs
---
layout: default
title: ここにページのタイトルが入ります
description: ここにページの説明が入ります
---
<table>
<thead>
<th>名称</th>
<th>学名</th>
<th>画像</th>
</thead>
<tbody>
{{#each gorillas.contents}}
{{> row name=name scientificName=scientificName image=image.url}}
{{/each}}
</tbody>
</table>
```
hbsの[Partials](https://handlebarsjs.com/guide/partials.html)という機能で、共通部品の`row.hbs`をパラメータ付きで呼び出すことができます。
### 共通部品
```html:src/components/row.hbs
<tr>
<td>
{{name}}
</td>
<td>
{{scientificName}}
</td>
<td>
<img src="{{image}}" alt={{name}}>
</td>
</tr>
```
## ローカルで動作確認
ブラウザで以下にアクセスして確認してみる
```
http://localhost:3000/
```
![スクリーンショット 2020-12-08 22.58.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242655/a239c8cc-65c1-b6a6-e58b-500a28c07423.png)
いい感じなのでGithubにコミットします :ok_woman_tone1:
## Netlifyへデプロイ
連携したGithubアカウントのリポジトリを選択します。
※ Netlifyの権限が足りない場合は、一部のリポジトリしか表示されないため、今回作成したリポジトリへのアクセス権を追加しましょう。
![app.netlify.com_start (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242655/c316739b-7fb8-d518-5448-ef037cba7ad1.png)
ビルドの設定などを行います。
![app.netlify.com_start (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242655/04b65d11-072e-1c52-2d92-943c0edf02b5.png)
少し待てば以下のような表示になります。
![スクリーンショット 2020-12-08 23.18.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242655/3a025eea-8f0c-a0d7-d0a3-fbd31a00c755.png)
## Netlify上で確認
デプロイ先のURLを確認し完成です。
![スクリーンショット 2020-12-08 23.19.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242655/565d820e-cff3-97c2-12a6-4ed504867ba9.png)
## さいごに
11tyであれば、VueやReactほどの機能はいらないけれども、多少パーツの共通化や繰り返しを行いたい場合も、学習コスト少なめで導入できます。
また、生成されるHTMLはVueやReact製のSSGと比べてコントロールしやすいため、成果物にSSGを使った形跡を残したくない場合にもおすすめです。
なお、VueやReact製のSSGは、学習コストはかかるものの、様々な機能があったり、DX(Developer Experience)が良かったりするので、是非そちらも試してみていただければと思います。
<details><summary>生成されたHTML</summary><div>
```html:index.html
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="index, follow">
<title>ここにページのタイトルが入ります</title>
<meta name="description" content="ここにページの説明が入ります">
<!--アイコンの設定-->
<link rel="icon" href="/favicon.ico">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<!--その他設定-->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="format-detection" content="telephone=no,address=no,email=no">
<meta name="theme-color" content="#fafafa">
<!--外部ファイルの読み込み-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/destyle.css@2.0.2/destyle.css">
</head>
<body><table>
<thead>
<th>名称</th>
<th>学名</th>
<th>画像</th>
</thead>
<tbody>
<tr>
<td>
ヒガシゴリラ
</td>
<td>
Gorilla beringei
</td>
<td>
<img src="https://images.microcms-assets.io/protected/ap-northeast-1:caccd6f4-3d77-4554-9063-9036c1d2f2df/service/jamstack-sample/media/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202020-01-30%2010.29.37.png" alt=ヒガシゴリラ height="150">
</td>
</tr>
<tr>
<td>
ニシゴリラ
</td>
<td>
Gorilla gorilla
</td>
<td>
<img src="https://images.microcms-assets.io/protected/ap-northeast-1:caccd6f4-3d77-4554-9063-9036c1d2f2df/service/jamstack-sample/media/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202020-01-30%2010.28.34.png" alt=ニシゴリラ height="150">
</td>
</tr>
<tr>
<td>
ニシローランドゴリラ
</td>
<td>
Gorilla gorilla gorilla
</td>
<td>
<img src="https://images.microcms-assets.io/protected/ap-northeast-1:caccd6f4-3d77-4554-9063-9036c1d2f2df/service/jamstack-sample/media/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202020-01-30%2010.27.28.png" alt=ニシローランドゴリラ height="150">
</td>
</tr>
<tr>
<td>
マウンテンゴリラ
</td>
<td>
Gorilla beringei beringei
</td>
<td>
<img src="https://images.microcms-assets.io/protected/ap-northeast-1:caccd6f4-3d77-4554-9063-9036c1d2f2df/service/jamstack-sample/media/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202020-01-30%2010.23.05.png" alt=マウンテンゴリラ height="150">
</td>
</tr>
<tr>
<td>
マウンテンゴリラ
</td>
<td>
Gorilla beringei beringei
</td>
<td>
<img src="https://images.microcms-assets.io/protected/ap-northeast-1:caccd6f4-3d77-4554-9063-9036c1d2f2df/service/jamstack-sample/media/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202020-01-30%2010.23.05.png" alt=マウンテンゴリラ height="150">
</td>
</tr>
</tbody>
</table>
</body>
</html>
```
</div></details>