cyokodog / study_nextjs

https://study-nextjs-omega.vercel.app
0 stars 0 forks source link

microcmsと連携してブログを作る #1

Open cyokodog opened 1 year ago

cyokodog commented 1 year ago

microcmsでアカウント作成

https://app.microcms.io/signup

サービス名を適当に決める(blog-sample-nextjsとか)

image

自分で決めるを選択

image

API名決める(blogとか)

image

リスト形式

image

とりあえず、タイトルと本文

image

追加から上記の様に入力。公開。

Next.js

npx create-next-app blog-with-microcms

Need to install the following packages:
  create-next-app@13.2.4
Ok to proceed? (y)
✔ Would you like to use TypeScript with this project? … No / Yes
✔ Would you like to use ESLint with this project? … No / Yes
✔ Would you like to use `src/` directory with this project? … No / Yes
✔ Would you like to use experimental `app/` directory with this project? … No / Yes
✔ What import alias would you like configured? … @/*
Creating a new Next.js app in /Users/cyokodog/src/github.com/cyokodog/study_nextjs/blog-with-microcms.

Using npm.

Initializing project with template: default

Installing dependencies:
- react
- react-dom
- next
- typescript
- @types/react
- @types/node
- @types/react-dom
- eslint
- eslint-config-next

npm run dev  # localhost:3000

microcms sdk

npm i microcms-js-sdk

libs/client.jsとか作る

import { createClient } from 'microcms-js-sdk';

export const client = createClient({
  serviceDomain: 'blog-sample-nextjs',
  apiKey: process.env.API_KEY,
});

API_KEYは、.env.localに以下のように設定。

API_KEY=xHJ4ayxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

pages/index.tsxを以下のように。

import { client } from '@/libs/client';
import Link from 'next/link';

interface BlogResponse {
  contents: Array<{
    id: string;
    title: string;
  }>;
}

//SSG
export const getStaticProps = async () => {
  const data = await client.get<BlogResponse>({ endpoint: 'blog' });
  return {
    props: { blog: data },
  };
};

export default function Home({ blog }: { blog: BlogResponse }) {
  return (
    <ul>
      {blog.contents.map((item) => (
        <li key={item.id}>
          <Link href={`blog/${item.id}`}>{item.title}</Link>
        </li>
      ))}
    </ul>
  );
}

個別ページ

pages/[id].tsxを作る

import { client } from '@/libs/client';

interface BlogByIdResponse {
  title: string;
  publishedAt: string;
  body: string;
}

export const getStaticProps = async (context: {
  params: {
    id: string;
  };
}) => {
  const id = context.params.id;
  const data = await client.get<BlogByIdResponse>({
    endpoint: 'blog',
    contentId: id,
  });
  return {
    props: {
      blog: data,
    },
  };
};

export const getStaticPaths = async () => {
  const data = await client.get<{ contents: Array<{ id: string }> }>({
    endpoint: 'blog',
  });
  const paths = data.contents.map((content) => `/blog/${content.id}`);
  return {
    paths,
    fallback: false, //設定パス以外は404になる
  };
};

export default function BlogId({ blog }: { blog: BlogByIdResponse }) {
  return (
    <main>
      <h1>{blog.title}</h1>
      <p>{blog.publishedAt}</p>
      <div dangerouslySetInnerHTML={{ __html: blog.body }}></div>
    </main>
  );
}

getStaticPathsで有効なパスも指定する必要がある。

CSS

デフォルトでCSS modulesが使えるので、コンポーネント毎に好きに使う。

styles/Home.modules.scss当たりに作成。

コンポーネント側で、

import styles from '../../styles/Home.module.scss';
...

export default function BlogId({ blog }: { blog: BlogByIdResponse }) {
  return (
    <main className={styles.main}>
      <h1 className={styles.title}>{blog.title}</h1>
      <p className={styles.publishedAt}>{blog.publishedAt}</p>
      <div
        className={styles.post}
        dangerouslySetInnerHTML={{ __html: blog.body }}
      ></div>
    </main>
  );
}

404ページ

pges/404.tsxを作れば、それが404ページになる

ビルド

npm run build

Route (pages)                              Size     First Load JS
┌ ● / (586 ms)                             2.33 kB        75.6 kB
├   /_app                                  0 B            73.3 kB
├ ○ /404                                   182 B          73.5 kB
├ λ /api/hello                             0 B            73.3 kB
└ ● /blog/[id] (1276 ms)                   461 B          73.7 kB
    └ css/09369be4643633c6.css             298 B
    ├ /blog/6ap88ct_e6 (722 ms)
    └ /blog/1osjnlgoe (554 ms)
+ First Load JS shared by all              73.9 kB
  ├ chunks/framework-cda2f1305c3d9424.js   45.2 kB
  ├ chunks/main-0ecb9ccfcb6c9b24.js        27 kB
  ├ chunks/pages/_app-ae907860a06fe57a.js  296 B
  ├ chunks/webpack-8fa1640cc84ba8fe.js     750 B
  └ css/2a5fdb6ede8d2764.css               635 B

λ  (Server)  server-side renders at runtime (uses getInitialProps or getServerSideProps)
○  (Static)  automatically rendered as static HTML (uses no initial props)
●  (SSG)     automatically generated as static HTML + JSON (uses getStaticProps)

npm run start

Vercelに公開

https://vercel.com/dashboard

image

githubリポジトリを選ぶ

image

API_KEYやルートディレクトリを指定して、deployボタン押す。

image

これでダッシュボードからサイトへ行ける

記事の更新

https://vercel.com/cyokodog/study-nextjs/settings/git プロジェクトのsettingsへ

image

mainブランチを指定して、create hooksをクリック

https://api.vercel.com/v1/integrations/deploy/prj_Zx....的なURLが表示される

microcmsのwebhooks設定へ https://blog-sample-nextjs.microcms.io/apis/blog/settings/webhook

image

追加で、カスタム設定を選ぶ

image

名前のvercelのwebhooks urlを指定

これで追加投稿されると再ビルドされる

cyokodog commented 1 year ago

micorocmsのsdkの型を上書きするという着想は参考になるかも