Next.js + Netlify + GraphCMSでJAMStackことはじめ


Ateam Finergy Inc. Advent Calendar 2020の13日目は、@murajun1978が担当します

はじめに

ちょっと前に、「NetlifyがNext.jsのPreview modeをフルサポートしたぜ!」ってアナウンスがありました
Preview modeといえば、Headless CMS?なので、GraphCMSと一緒に試してみます

ご注意:
このサンプルでは、Netlify Functionsを使います
Netlifyのフリープランで利用可能ですが、125k/per monthを超えると課金対象になるのでご注意ください

ちなみに、Netlify Functionsは、AWS Lambdaで動いてます
料金体系は違いますが、実行時間の制限などは同じです

GraphCMSとは

GraphCMS
APIサーバがGraphQLなCMSです
ダッシュボードにはGraphQLのPlaygroundもあったりします

やってみる

環境構築

Next.jsの環境を構築します

$ npx create-next-app my-app

next-on-netlify

Next.jsをNetlifyにデプロイするためのパッケージをインストールします

$ npm install next-on-netlify

Next.jsをexperimental-serverless-traceモードに変更
最初はserverlessモードに設定していたのですが、Preview modeでは動作しませんでした
FYI: https://github.com/netlify/next-on-netlify/issues/99

next.config.js
module.exports = {
  target: 'experimental-serverless-trace',
};
netlify.toml
[build]
  command   = "npm run build"
  functions = "out_functions"
  publish   = "out_publish"

graphql-request

いつもApollo Clientですが、たまには違うものをと探してみつけたGraphQL Client
graphql-request

$ npm add graphql-request graphql

でも、僕はやっぱりApolloが使いやすい

GraphCMS

GraphCMSでProjectを作成して、API Endpointの設定をします

  • Public API permissions
    パブリックアクセスの設定です
    デフォルトではQuery,Mutationsともに許可されていません

  • Permanent Auth Tokens
    トークンを払い出して、トークン毎にpermisionの設定を行います
    このサンプルではこちらを使います
    Draft, Publishedどちらも許可して、デフォルトはPublishを取得するように設定しました

Netlify

Netlifyにデプロイしてみます

siteを作成して、指定のブランチを設定するだけです(簡単!
あと、GraphCMSのAPI ENDPOINTとtokenを環境変数にセットします

deploy settingsのenvironmentに追加します

あとはremoteブランチにpushすれば、自動でbuildが実行されます
buildに成功すれば、siteにアクセスすると表示きるはずです

ちなみにblogページを実装しただけのLighthouseのスコア

Preview mode

公開前に記事をプレビューモードで表示してみます

まずは、Preview modeのエンドポイントを作成します

preview.js
export default async (req, res) => {
  if (req.query.secret !== process.env.PREVIEW_MODE_SECRET) {
    return res.status(401).json({ message: 'Invalid token' })
  }

  res.setPreviewData({})
  res.redirect('/blog')
}

トークンをチェックしてOKであれば、/blogにリダイレクトします
今回はトークンでチェックしてますが、OAuthで認証するのが正しいかとおもいます

Preview modeでアクセスが来たときに、Draftの記事も表示できるようにします

blog.js
export const getStaticProps = async () => {
  const client = new GraphQLClient(process.env.GRAPHCMS_API, {
    headers: {
      authorization: `Bearer ${process.env.GRAPHCMS_TOKEN}`
    }
  })
  const { posts } = await client.request(query)

  return {
    props: {
      posts
    }
  }
}

まずはPreview modeではなく、普通にアクセスしてみます

Preview modeでアクセスしてみます

/api/preview?secret=xxx にアクセスします

一番下にSample PostってDraftの記事も表示されていますね

あと、__next_preview_dataってcookieがセットされていますよね?
これがPreview modeである印です
なので、このCookieを削除してリロードすれば、Draftの記事は表示されません

まとめ

記事を作成、編集すると、ビルドはNext.jsがいい感じにやってくれます
なにより、デプロイって工程がなくなります(メリットは他にもたくさんあります)
デプロイは、GitHub Actionsとかで自動化することはできると思いますが

Next.jsのPreview modeが面白いのは、本番環境と同じURLでプレビューできるってとこです
Stagingで記事を書いてプレビューして、本番環境にコピーしてなんてこともしなくてよくなりますし、
Preview用のエンドポイントの作成も不要です

あと、OSSのCMSもたくさんあるみたいなので、こちらも試してみたいと思います