こんにちは、柴田です。
今回は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についてはこちらの記事で詳しく説明しております。
処理の流れ
ブログを作成する流れを考えてみましょう。
大枠はシンプルです。
- GulpからヘッドレスCMSのAPIを呼ぶ
- レスポンス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-MICROCMS-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-MICROCMS-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/microcmsio/microcms-sample/tree/master/gulp-ejs-microcms-blog
Jamstack構成にする
API呼び出しからの、レスポンスをEJSに渡してHTMLへ変換するところまで完了しました。
ここまで来たらあと少しでJamstackな構成になります。
Jamstackのおさらいです。
これで言うと、今回はヘッドレスCMSとしてmicroCMS、静的サイトジェネレータはGulp+EJSという構成になります。
ホスティングはNetlifyを使うことにします。
残作業としては下記になります。
- microCMSからNetlifyへのWebhook連携
- その際にNetlifyからGulpのビルドを走らせる
- ビルド完了後にデプロイを行う
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をよろしくお願いいたします!