Webデザイン学科
授業資料

JavaScript演習
[SSG]静的サイトジェネレーター「Eleventy」

概要解説

前回に引き続き、静的サイトジェネレーター「Eleventy(11ty)」を使って Web サイトを制作していきます。
複数ファイルになった場合に、どのように出力されるのか、設定によるソースディレクトリなどの変更方法を演習していきます。

JavaScript クイズ

15 分以内に回答して、送信してください。

  • 6 月 14 日(火) 今回も、前回同様、初歩的な文字の追加の確認問題です。

内容

.
├── _includes/
│   └── layout.njk
├── index.md
└── package.json
  • 対応テンプレート形式
  • URL 設計
  • Nunjucks の記法
  • front-matter
  • front-matter 以外のソースデータ
    • テンプレートデータファイル
    • ディレクトリデータファイル
    • グローバルデータファイル

授業資料

対応テンプレート形式

様々な、テンプレートに対応しているので、html や他のテンプレート形式で書いても OK。

nunjacks/index.njk

{% set message = 'これは、nunjacksです。' %}
<p style="background-color:lightgray;">{{ message }}</p>

pug/index.pug

p(style="background: gray")= 'これは、pugです。'

html/index.html

<p style="background-color: #eee">htmlファイルです。</p>

index.md

---
layout: layout.njk
---

# 見出し

本文

- [html](./html)
- [nunjucks](./nunjucks)
- [pug](./pug)

一度、元に戻してabout.mdを作成します。

# 所属

トライデントコンピュータ専門学校 Web デザイン学科

ソースディレクトリの変更

module.exports = {
	dir: {
		input: 'src'
	}
};

対象となるファイルを設定

対象ファイルを設定することで、不必要なビルドを防ぐことができます。
.eleventy.js に記述する方法と.gitignore もしくは、.eleventyignore に記述する方法があります。
簡単な.eleventyignore を使いますので、作成しておいてください。
.eleventyignore ファイルのあるディレクトリからのパスを明記します。
対象ファイルが src 内の about.md であれば、src/about.mdと記述します。

README.md #ファイル
_drafts/ #フォルダ
secretNunjucksTemplates/anotherFolder/**/*.njk  #相対パス

Eleventy での Nunjucks 変数

front-matter に title という名前でページのタイトルを出力してみます。

index.njk

---
title: EleventyはNunjucksテンプレートが使える
---

<h1>{{ title }}</h1>

_includes/layout.njk

---
title: レイアウトに指定したタイトル
---

<!DOCTYPE html>
<html lang="ja">
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>{{ title }}</title>
	</head>
	<body>
		{{ content | safe }}
	</body>
</html>

index.njk 初期化

ファイルが煩雑になったので、index.njk をシンプルなものに変更しておきます。

---
title: 記事タイトル
layout: layout.njk
---

<h1>{{ title }}</h1>
<ul>
	 
	<li><a href="./article">article</a></li>
</ul>

article.njk

新たに article.njk を src 内に作成します。

---
title: 記事タイトル
authors:
  - name: oda
    title: Jamstackエンジニア
  - name: toyotomi
    title: フロントエンド・エンジニア
---

<h1>{{ title }}</h1>
<div>メイン著者: {{ authors[0].name }}</div>

for 記法で取得します。

<ul>
	{% for author in authors %}
	<li>{{ author.name }} : {{ author.title }}</li>
	{% endfor %}
</ul>

Nunjucks の for 文法では{% else %}を入れることで、0 件だった場合の表示を出力できます

<ul>
	{% for author in authors %}
	<li>{{ author.name }} : {{ author.title }}</li>
	{% else %}
	<li>著者はいません!</li>
	{% endfor %}
</ul>

for の中では、loop という変数に何回目のループかを表す loop.index や、最初の繰り返しと最後の繰り返しを判定するための loop.last や loop.first などが使えます。
if 文法と組み合わせます。

<ul>
	{% for author in authors %} {% if loop.first %}
	<li><strong>{{ author.name }} : {{ author.title }}</strong></li>
	{% else %}
	<li>{{ author.name }} : {{ author.title }}</li>
	{% endif %} {% endfor %}
</ul>

テンプレートデータ(JSON)

article.njk から著者情報を削除し、article.njk と同じ場所に article.11tydata.json を作り、JSON 形式で著者情報を入れます。

article.11tydata.json

{
	"authors": [
		{
			"name": "oda",
			"title": "Jamstackエンジニア"
		},
		{
			"name": "toyotomi",
			"title": "フロントエンド・エンジニア"
		}
	]
}

テンプレートデータ(JavaScript)

JavaScript での方法は、JSON ファイルの拡張子を js に変え、ファイルのコードは単純に Object 形式で module.exports に代入するだけです。

article.11tydata.js

module.exports = {
	authors: [
		{
			name: 'oda',
			title: 'Jamstackエンジニア'
		},
		{
			name: 'toyotomi',
			title: 'フロントエンド・エンジニア'
		}
	]
};

JavaScript なので変数を定義したり、計算したり、必要ならば他のライブラリを読み込んで処理することもできます

const engineer = 'エンジニア';
module.exports = {
	authors: [
		{
			name: 'oda',
			title: 'Jamstack' + 'エンジニア'
		},
		{
			name: 'toyotomi',
			title: `フロントエンド・ ${engineer}`
		}
	]
};

JavaScript 形式だと、 module.export で function が扱えます。データは function を実行し、return された値になります。

module.exports = function () {
	const engineer = 'エンジニア';
	return {
		authors: [
			{ name: 'oda', title: `Jamstack${engineer}` },
			{ name: 'toyotomi', title: `フロントエンド・${engineer}` }
		]
	};
};

API からデータ取得

node-fetch というライブラリを利用していますので、事前にインストールしておきましょう。
version3 以降だとエラーになりますので、@2 を付随して version2 系をインストールします。

npm install node-fetch@2

article.11tydata.js

const fetch = require('node-fetch');
module.exports = function () {
	return fetch('https://trident-web.kikirara.jp/11ty/authors.json').then((res) => res.json());
};

ディレクトリデータファイル

データによっては、複数のテンプレートで共通して情報を使いたい場合もあります。
テンプレートの名前ではなく、ディレクトリの名前に加えて.11tydata.js、または.11tydata.json というファイルを用意すると、そのディレクトリのテンプレート共通で使えるデータとなります。

グローバルデータファイル

グローバルデータファイルは、サイト全体で利用できるデータファイルです。
_data というディレクトリに配置されることで利用できます。
こちらも JSON から非同期処理まで使えます。

.
├── _site/
├── src/
│    ├── _includes/
│    │    └── layout.njk
│    ├── index.njk
│    ├── _data/
│    │    └── metadata.json
│    └── articles/
│         ├── articles.11tydata.js
│         └── 2022-12-24.njk
└── package.json
{
	"sitename": "11tyサイト"
}

データファイルの優先順位

データの優先順位は、データファイルより front-matter が優先となります。
また、それぞれ範囲が狭いものから優先となります。

  • front-matter なら、テンプレートに書かれたもの → レイアウトに書かれたものの順
  • データファイルなら、テンプレートデータファイル → ディレクトリデータファイル → グローバルデータファイルの順 です。

煩雑になるため、API アクセスが必要なものはグローバルデータファイル、
個別のテンプレートに必要なものはテンプレートの front-matter に書き、その他のものは極力使わないようにします。

2022-06-14
Hideo kawaguchi