microCMS

Gulp + EJS + microCMSでJamstackな構成を実現する

チュートリアル
2020/03/10 柴田 和祈

こんにちは、柴田です。
今回はGulpを使ったJamstackのチュートリアルのご紹介です。
いつの間にかにGulpは4系になっていたんですね〜。(しばらく触っていなかったので久々でした)

Gulpとは

2015年あたりで一斉を風靡したタスクランナーというやつですね。
タスクを記述することで、scssをcssに変換したり、JavaScriptをminifyしたり、ブラウザをホットリロードさせたり色々できます。

EJSでHTMLを静的生成

EJSというテンプレートエンジンをご存知でしょうか。
JSONをEJSテンプレートに渡すことで値を動的にセットできるので、ExpressなどNodeのフレームワークと組み合わせて使われることが多いです。

GulpからEJSテンプレートにJSONを渡してHTMLを生成するという方式もあります。
その場合、大抵JSONファイルはローカルに置かれており、ファイルを直接読み込んでEJSに渡す形が多いのですが、これをヘッドレスCMS経由でやりたいというお話をいただきました。

それってビルド・デプロイまでちゃんと設定できれば、もはやJamstackじゃん!ということで早速サンプルを作ってみました。
ちなみにJamstackについてはこちらの記事で詳しく説明しております。

処理の流れ

ブログを作成する流れを考えてみましょう。
大枠はシンプルです。

  1. GulpからヘッドレスCMSのAPIを呼ぶ
  2. レスポンスJSONをEJSテンプレートに渡し、HTMLを生成


EJSテンプレートは以下のような階層になっています。

index.ejs    // トップページテンプレート
blog/
    index.ejs    // 記事一覧ページテンプレート
    __slug.ejs    // 記事詳細ページテンプレート


これを次のようにHTML生成をしたいと思います。

index.html    // トップページ
blog/
    index.html    // 記事一覧ページ
    slug01/
        index.html    // 記事詳細ページその1
    slug02/
        index.html    // 記事詳細ページその2


ここで出てくるslugとはブログ記事のURL末尾に相当する部分を指します。
また、URLバーからslug01.htmlという指定をしたくなかったため、slugのディレクトリを作成し、中にindex.htmlを置く方式とします。
そうすることで /blog/slug01 にアクセスすると中身のindex.htmlが表示されます。(Nuxtの静的生成に倣いました)

ヘッドレスCMSとして利用するのはmicroCMSです。

実際のコード

まず、以下のようなgulpfile.jsを書いてみました。

const gulp = require("gulp");
const ejs = require("gulp-ejs");
const rename = require("gulp-rename");
const fetch = require("node-fetch");

gulp.task("ejs", () => {
  return fetch(
    "https://example.microcms.io/api/v1/gulp-blog",
    {
      headers: {
        "X-API-KEY": "dc59f358-4622-471f-8d1e-6c7a6f969558"
      }
    })
  .then(res => res.json())
  .then(data => {
    gulp
      .src(["src/ejs/**/*.ejs", "!src/ejs/**/_*.ejs"])
      .pipe(ejs(data))
      .pipe(rename({ extname: ".html" }))
      .pipe(gulp.dest("dist"));
  });
});


gulpからAPIを呼ぶために、node-fetchというパッケージを利用しています。
最初にAPIを呼び出し、レスポンスが取得できたタイミングでEJSからHTML変換の処理を行います。
変換の際に、アンダースコア(_)が先頭に付いているEJSファイルはinclude用のファイルなので除外します。

ここで一つ問題が発生します。
固定ページ(トップや一覧ページ)は簡単に生成できますが、記事詳細ページなどURLが動的であるページをどのように生成すれば良いでしょうか。

そうです、先ほどのslug部分の話です。
基本的にはsrc/ejs以下の階層をそっくりそのままdist配下に置くことになりますが、動的ページはそのままではいけないので、「slug名のディレクトリ + index.html」を作成します。
slug名はmicroCMSのレスポンスに含まれる個々の記事idを用います。

gulp.task("ejs", () => {
  return fetch(
    "https://example.microcms.io/api/v1/gulp-blog",
    {
      headers: {
        "X-API-KEY": "dc59f358-4622-471f-8d1e-6c7a6f969558"
      }
    })
  .then(res => res.json())
  .then(data => {
    // 記事ページ
    for (const item of data.contents) {
      gulp
        .src(["src/ejs/**/__*.ejs"])
        .pipe(ejs(item))
        .pipe(rename({ basename: `${item.id}/index`, extname: ".html" }))
        .pipe(gulp.dest("dist"));
    }

    // その他ページ
    gulp
      .src(["src/ejs/**/*.ejs", "!src/ejs/**/_*.ejs"])
      .pipe(ejs(data))
      .pipe(rename({ extname: ".html" }))
      .pipe(gulp.dest("dist"));
  });
});


動的ページのEJSファイルはアンダースコアを2個つなぎとして、区別しています。
そうすることで、その他ページの変換時にも先頭がアンダースコアという条件にマッチされ、除外することができます。

その他、一式のコードはGitHubに置いてあるのでお気軽にお試しください。
https://github.com/wantainc/microcms-sample/tree/master/gulp-ejs-microcms-blog

Jamstack構成にする

API呼び出しからの、レスポンスをEJSに渡してHTMLへ変換するところまで完了しました。
ここまで来たらあと少しでJamstackな構成になります。

Jamstackのおさらいです。


これで言うと、今回はヘッドレスCMSとしてmicroCMS、静的サイトジェネレータはGulp+EJSという構成になります。
ホスティングはNetlifyを使うことにします。

残作業としては下記になります。

  1. microCMSからNetlifyへのWebhook連携
  2. その際にNetlifyからGulpのビルドを走らせる
  3. ビルド完了後にデプロイを行う


microCMSからNetlifyへのWebhook連携

Netlifyの Settings > Build & deploy > Build hooks で新しくビルドフックを作成しましょう。
作成すると、Webhook URLが割り当てられます。

次に、microCMSにて API設定 > Webhook > Netlify を開き、発行されたWebhook URLを設定します。

これでWebhook連携は完了です。
簡単ですね。

Netlifyでのビルド設定

次に、Netlifyのビルドで今回のGulp処理が動くように設定します。
再びNetlifyに戻り、Settings > Build & deploy > Build settings を開きましょう。
ここにビルドコマンドと、デプロイするディレクトリを指定します。
今回の例で言うと、npm run build でEJSとSassのビルドが行われ、distディレクトリ以下に展開されるので、次のように指定します。

これでビルド設定も完了しました。
以上で、記事をmicroCMSから更新、またはソースコードをGitHubにプッシュするとNetlifyのビルドが走り、自動でデプロイがされるようになります。

おわりに

今回は、GulpでJamstackを実現するサンプルを紹介しました。
Web制作現場ではまだまだ使っている方も多いと思うので、ぜひ試してみていただけると幸いです。

-----

microCMSは日々改善を進めています。
ご意見・ご要望は管理画面右下のチャット、公式Twitterメールからお気軽にご連絡ください!
引き続きmicroCMSをよろしくお願いいたします!

ABOUT ME

柴田 和祈
microCMSのデザイン、フロントエンド担当 / ex Yahoo / 2児の父 / 著書「React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで 」 / JAMstack