LoginSignup
11
8

More than 3 years have passed since last update.

11ty/eleventy × microCMS を使ったJamstackなサイトの作り方

Posted at

この記事はJamstack Advent Calendar 2020の8日目の記事です。

はじめに

SSGといえば、東京都 新型コロナウイルス感染症対策サイトで使われているVue製のNuxt.jsやReact製のGatsbyNextが有名です。
しかし、VueやReactで書かなければいけないので、Web初学者からすると敷居が高くなかなか手が出しづらいと思います。

一方、11ty/eleventyの基本はHTML(テンプレートエンジン)なので、多少テンプレートエンジンの文法を覚える必要はありますが、
VueやReactと比較すると学習コストは低いと思いますので手を出しやすいかと思います。

11ty/eleventy とは :thinking:

  • 11ty/eleventyzachleat氏によって制作さいれている静的サイトジェネレーター(SSG)
  • テンプレートエンジンの詰め合わせのようなもの
    • デフォルトで以下の言語に対応しています。
      • HTML(.html)
      • Liquid(.liquid)
      • EJS(.ejs)
      • Markdown(.md)
      • Handlebars(.hbs)
      • Mustache(.mustache)
      • Haml(.haml)
      • Pug(.pug)
      • Nunjucks(.njk)
      • JavaScript(.11ty.js)
  • 今回は利用しませんが、ローカル開発用のサーバも組み込まれています。

事前準備

  • microCMS でユーザ登録しておく。(無料
  • Github でユーザ登録し、(プライベート)リポジトリを作成しておく。(無料
  • Netlify でユーザ登録し、Github連携しておく。(無料

また、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を使って投入します。

ページのコンテンツ

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という機能で、共通部品のrow.hbsをパラメータ付きで呼び出すことができます。

共通部品

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

いい感じなのでGithubにコミットします :ok_woman_tone1:

Netlifyへデプロイ

連携したGithubアカウントのリポジトリを選択します。
※ Netlifyの権限が足りない場合は、一部のリポジトリしか表示されないため、今回作成したリポジトリへのアクセス権を追加しましょう。

app.netlify.com_start (2).png

ビルドの設定などを行います。
app.netlify.com_start (3).png

少し待てば以下のような表示になります。
スクリーンショット 2020-12-08 23.18.21.png

Netlify上で確認

デプロイ先のURLを確認し完成です。
スクリーンショット 2020-12-08 23.19.20.png

さいごに

11tyであれば、VueやReactほどの機能はいらないけれども、多少パーツの共通化や繰り返しを行いたい場合も、学習コスト少なめで導入できます。
また、生成されるHTMLはVueやReact製のSSGと比べてコントロールしやすいため、成果物にSSGを使った形跡を残したくない場合にもおすすめです。
なお、VueやReact製のSSGは、学習コストはかかるものの、様々な機能があったり、DX(Developer Experience)が良かったりするので、是非そちらも試してみていただければと思います。

生成された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>

11
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8