LoginSignup
1
2

More than 1 year has passed since last update.

Next + MicroCMS + Netlify でプレビュー機能を作る

Posted at

この記事の目的

  • MicroCMSのプレビュー機能が出来るようになること。
  • プレビュー機能作成でつまづいたのでメモ

前提

  • 既にnetlifyに対してデプロイを行なっている
  • microCMSとnext.jsの連携も行なっている
  • 基本的なページは完成している(react等で実装が終わっている)

環境

package.json
{
  "name": "myProject",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "microcms-js-sdk": "^2.0.0",
    "next": "12.1.5",
    "react": "18.0.0",
    "react-dom": "18.0.0"
  },
  "devDependencies": {
    "@types/node": "17.0.26",
    "@types/react": "18.0.6",
    "@types/react-dom": "18.0.2",
    "eslint": "8.14.0",
    "eslint-config-next": "12.1.5",
    "typescript": "4.6.3"
  }
}

1. targetをserverlessにする

参考: https://www.netlify.com/blog/2020/10/27/preview-mode-for-next.js-now-fully-supported-on-netlify/

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  // ...
  target: 'serverless',
  // ...
}

module.exports = nextConfig

2. preview用のfunction実装

参考: https://nextjs-ja-translation-docs.vercel.app/docs/advanced-features/preview-mode

src/pages/api/preview.ts
export default function handler(req: any, res: any) {
  // 後々に記述するが、これらのqueryの名前は自分で決める。contentTypeが今回はページのpathになっている
  // pathが /articles/articleId の構成のサイトなら、 contentType = articles, contentId = articleId となる
  const contentType = req.query?.contentType
  const contentId = req.query?.contentId
  // draftKeyは下書き用のkey。後々出てくる
  const draftKey = req.query?.draftkey
  if (!contentType || !contentId || !draftKey) {
    return res.status(401).json({ message: 'Invalid params' })
  }
  res.setPreviewData({
    contentId,
    draftKey,
  })
  // ここは、ページ設計によるが、next+netlifyで作っていれば大体こうなるはず。
  res.writeHead(302, {
    Location: `/${contentType}/${contentId}`,
  })
  return res.status(200).json({ message: 'success' })
}

3. page側実装

src/pages/articles/[id].tsx
import { MicroCMSQueries } from 'microcms-js-sdk'
import { Article, getArticle } from '../../apis/microCms'

type Props = {
  res: Article
}

type Params = {
  id: string
}

type _PreviewData = {
  contentId: string
  draftKey: string
}


const ArticleDiv: NextPage<Props> = ({ res }) => {
  // この辺は本件とは関係ないので省略
  return (<div></div>)
}

export const getStaticPaths: GetStaticPaths<Params> = async () => {
  const queries: MicroCMSQueries = { fields: 'id', limit: 100 }
  const res = await getArticles(queries)
  return {
    paths: res.contents.map((article) => ({ params: { id: article.id } })),
    fallback: false,
  }
}

// contextに、preview.tsで取得したcontentIdとdraftKeyが格納されている
export const getStaticProps: GetStaticProps<Props, Params> = async (context) => {
  const previewData = context.previewData as _PreviewData
  const draftKey =
    String(context.params!.id) === String(previewData?.contentId) ? previewData?.draftKey : ''
  const res = await getArticle(context.params!.id, draftKey)
  return {
    props: {
      res,
    },
  }
}

export default ArticleDiv
src/apis/microCms.ts
import { MicroCMSQueries } from 'microcms-js-sdk'
import { GetListDetailRequest, GetListRequest, MicroCMSListResponse } from 'microcms-js-sdk'

export type Article = {
  id: string
  title: string
}

export async function getArticles(queries?: MicroCMSQueries): Promise<MicroCMSListResponse<Article>> {
  const getListRequest: GetListRequest = {
    endpoint: 'articles',
  }
  if (queries) {
    getListRequest.queries = queries
  }
  const res = await cmsClient.getList(getListRequest)
  return res
}

export async function getArticle(id: string, draftKey?: string): Promise<Article> {
  const detailQueries: GetListDetailRequest = { endpoint: 'articles', contentId: id }
  if (draftKey) {
    detailQueries.queries = { draftKey }
  }
  const res = await cmsClient.getListDetail(detailQueries)
  return res
}

ここまで終わったら、netlifyにデプロイする

4. microCMSで設定

image.png

API設定画面より、
microCMSに従って、myprojectやcontentType部分を自分のプロジェクトに置き換えれば完了

5. プレビュー実行

image.png

記事ページが下書き状態で、画面プレビューボタンを押せば画面が見られる

おわりに

next.config.js 部分はもう少し知見が欲しいので、詳しい方いたらコメントお願いします

1
2
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
1
2