追記:
Next.js v9.3以降SSGに関するAPIの変更や、環境変数の扱い方が変わったので、対応した記事に書き換えました。
はじめに
この記事はJAMstack Advent Calendar 2019 7日目の記事です。
こんにちはかみむらです。最近は、Twitter上でJAMstackアーキテクチャーについての情報をシェアしています。
先日、個人のポートフォリオをJAMstackアーキテクチャーな構成で立ち上げました。このサイトの技術スタックはNext.js(静的サイト) + microCMSでホスティングサービスにNetlifyを利用しています。
JAMstackは静的なJavaScript、独立したAPI、ビルド済みのマークアップを総称したアーキテクチャーで、今回作成したウェブサイトはこれらの要件を満たしていることになります。もしJAMstackアーキテクチャーをもっと詳しく知りたい場合は、こちらの公式サイトをご参照ください。
https://jamstack.org/
そして、Googleが公式で開発しているウェブサービスの品質を測定できるツール「Lighthouse」でポートフォリオの数値を測定した結果がこちらです。環境で多少の誤差はありますが、非常にハイパフォーマンスな数値が出ています。
JAMstackアーキテクチャーでウェブを構成する利点の一つに、JavaScript(フロントエンド)に重点を置けることがあります。ヘッドレスCMSのmicroCMSやNetlifyの登場で、今までサーバーにかけていた工数が大幅に減るので、その分パフォーマンスチューニングやUX向上に時間をかけることが出来ます。そして、フロントエンドに注力できることはフロントエンドの開発者にとってDXを高めることに繋がります。
デモ
こちらにNext.js + microCMSのデモコードがあります。
https://github.com/hiro08gh/next-microcms-ssg
今回作るJAMstackなサイトの全体像
上記で説明した技術スタックを使っていきます。フロントエンドはNext.jsで構成して、apiをmicroCMSでコンテンツ管理をします。microCMSとは日本製のヘッドレスCMSで、リクエストヘッダーにapiキーを含めて送ることで、データを取得することができます。そして、Next.jsで生成する静的なファイルをNetlifyでホスティングします。
microCMSのコンテンツモデル作成
まずはmicroCMSでコンテンツモデルを作成します。下記のリンクからアカウント作成を行ってください。
https://microcms.io/
作成するコンテンツモデルは簡易的なブログを想定しています。
blogsというモデルに対して、tagsというモデルがリレーションされています。そして、blogsはtagsを複数持つことが出来ます。それでは早速作っていきましょう。
アカウント作成後、サービス名とサービスIDを入力します。サービスIDはエンドポイントのドメインになるので、関連するワードにしたほうがいいかもしれません。
ステップ2のサービス画像は後から設定できるのでスキップでも大丈夫です。
それではコンテンツを作成していきます。まずはタグのコンテンツモデルから作成します。APIの名前とエンドポイントを入力します。ここではタグとtagsを入力しました。
そしてapiの型を設定します。こちらはリスト形式にします。
APIスキーマを定義します。タグはnameのスキーマを一つ持っています。
続いてブログのコンテンツモデルを作成します。API名はブログでエンドポイントはblogsにしました。
ブログのコンテンツモデルはこちらです。タグのスキーマを複数コンテンツ参照にします。これでブログとタグのリレーションを作ることができました。
microCMSのコンテンツモデルができました。フロント側で取得するために、いくつかコンテンツを作成してみましょう。
サイドバーにあるタグをクリックして、追加をクリックします。
タグ名を入力します。入力値はなんでも大丈夫です。そして公開します。
これでリレーションを含むコンテンツを作成出来てしまいました。microCMSは導入障壁が非常に低いので、最高ですね。
Next.jsプロジェクトの作成
次にJAMstackのJ(JavaScript)部分を構築していきます。create-next-appという便利なCLIライブラリがあるので、これでプロジェクトの雛形を作っていきます。
$ npx create-next-app my-app
Default Starter appを選択してプロジェクトを作成してください。
microCMSではリクエストヘッダーにapiキーを含めてリクエストを送ります。セキュリティー確保のため、apiキーは.env
ファイルに保存する必要があります。
そして.env.development.local
ファイルを作成して、microCMSのAPIキーを追加します。XXXXXXの部分を置き換えてください。APIキーはmicroCMSの設定から取得することが出来ます。
API_KEY=XXXXXXXXXXXXXXXX
これでプロジェクトのセットアップは完了です。
microCMSからデータを取ってくる処理
microCMSのコンテンツデータを取得します。フロントエンド側で取得するため、isomorphic-unfetchをインストールします。
$ yarn add isomorphic-unfetch
追記: isomorphic-unfetchは必要なくなりました。データ取得はfetch apiですることができます。
そして、pagesフォルダにあるindex.jsの内容を書き換えます。https://your.microcms.io/api/v1/blogs/
には先ほど作成したmicroCMSのURLを入れます。
import fetch from 'isomorphic-unfetch';
import Link from 'next/link';
const Home = ({blogs}) => {
return (
<div>
<h2>最新の記事</h2>
<div>
{blogs.map(blog => (
<React.Fragment key={blog.id}>
<Link href="/blogs/[id]" as={`blogs/${blog.id}`}>
<a>
<h2>{blog.title}</h2>
</a>
</Link>
{blog.tags.map(tag => (
<React.Fragment key={tag.id}>
<span>{tag.name}</span>
</React.Fragment>
))}
</React.Fragment>
))}
</div>
</div>
);
};
export const getStaticProps = async () => {
const key = {
headers: {'X-API-KEY': process.env.API_KEY},
};
const res = await fetch(
`https://your.microcms.io/api/v1/blogs/`,
key,
);
const data = await res.json();
return {
props: {
blogs: data.contents,
}
}
};
export default Home;
ここではgetStaticProps
という静的なメソッドを使って、ページを読み込む前にデータを取得してます。なので、取得したデータを元に静的なHTMLを生成することできます。
そしてLinkのhref
でルートの遷移先をしていします。blogsが持っているidを元にします。ダイナミックルーティングをする場合、Linkにas
を指定する必要があります。これは、ブラウザのURLバーに表示されるパスです。
個別ページの作成
記事のリストページができました。次に記事の個別ページを作成していきます。microCMSでapiのプレビューをすることが出来ます。
pagesフォルダの中にblogsフォルダを作成してその中に**[id].js**を作成します。
/blogs/[id].js
import fetch from 'isomorphic-unfetch';
const BlogId = ({blog}) => {
return (
<div>
<h1>{blog.title}</h1>
<div>
{blog.tags.map(tag => (
<React.Fragment key={tag.id}>
<span>{tag.name}</span>
</React.Fragment>
))}
</div>
<div dangerouslySetInnerHTML={{__html: `${blog.body}`}}></div>
</div>
);
};
export const getStaticPaths = async () => {
const key = {
headers: {'X-API-KEY': process.env.API_KEY},
};
const res = await fetch('https://your.microcms.io/api/v1/blogs', key);
const repos = await res.json();
const paths = repos.contents.map(repo => `/blogs/${repo.id}`);
return {paths, fallback: false};
};
export const getStaticProps = async context => {
const id = context.params.id;
const key = {
headers: {'X-API-KEY': process.env.API_KEY},
};
const res = await fetch(
`https://your.microcms.io/api/v1/blogs/${id}`,
key,
);
const blog = await res.json();
return {
props : {
blog: blog,
}
};
};
export default BlogId;
先ほどとは違って、getStaticPathsが登場しました。これは、Dynamic Routeの際にページ毎に静的なHTMLを生成するAPIです。ここでは、microCMSの個別ブログのデータを取得して静的なHTMLを生成しています。
ここではcontext.query
でid情報を取得しています。取得したid情報を元に、microCMSから個々のデータを取り出します。
一度これを実行してみましょう。
$ yarn dev
そして個別ページも取得することができました。
microCMSで作成したデータのリストと個別のデータを取得することができました。スタイルを整えればブログになりますね。
Next.jsのビルド設定
簡易的ではありますが、microCMSでコンテンツを管理できるブログが作成できました。
Next.jsでは静的なHTMLをexportするためのコマンドnext export
があります。これを実行すると、out
というフォルダが生成されます。package.jsonに追加しましょう。
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
//追記
"export": "yarn run build && next export"
},
これで一通りできました。ちゃんとできるか試しにローカルでビルドしてみましょう。まずは、ローカルでビルドするためのenvファイルを作成します。内容は先ほどと同じです。
API_KEY=XXXXXXXXXXXXXXXX
$ yarn export
ここからはNetlifyとGitHubを連携する必要があるので、レポジトリを作って、ソースコードをプッシュしてください。
Netlifyにビルドする
ビルドするための設定します。
アカウントを認証後、ダッシュボードのNew site from Gitをクリックします。
今回はGitHub上にソースコードをあげたので、GitHubを選択します。すると、認証を求められます。
認証に成功すると、自分のレポジトリからどのレポジトリをホスティングするか選択する必要があります。自分がプッシュしたプロジェクトを選択しましょう。
静的ファイルをビルドするコマンドとディレクトリーを指定します。これは先ほど確認したものです。
Netlifyで環境変数を設定する
Advanced build settingsから環境変数を設定します。ここでは.envファイルに入れた、microCMSのapiキーを指定します。これでDeploy siteをしてみましょう。
無事ビルドが完了して、デプロイされるとURLが発行されます。
ローカルで確認して内容が確認できます。これでJAMstackなサイトを作る第一歩として一連の流れが終わりました。
最後に
今回はJAMstackアーキテクチャーの導入部分として、簡易的なブログを作成しました。microCMSは無料枠の範囲が非常に広いので、試しに使ってみてください。