microCMS×Next.jsモダンフロントエンドでJamstackなブログを作ろう

# 前提知識
- React, Next.js基礎
- HTML,Sassの基礎
- Linaxの基礎

## 概要
会社でコーポレートサイトをリニューアルすることになり、Next.jsを採用しました！
動的なブログ機能を実装する必要があったため最近話題のヘッドレスCMSに手を出してみました！

### Next.jsをインストール
まずはちょちょっとNext.jsで環境構築しましょう。
今回はわかり安くデスクトップに作成していきます！

```
cd ~/Desktop/
mkdir next-js
cd next-js
npm init next-app　blog
cd blog
yarn dev

```
![スクリーンショット 2021-02-05 20.32.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/3868e507-d6b3-4699-ceef-e3f0b5095af2.png)

こいつが出たら成功です！
エラーが出たらyarn -v、npm -v ,node-v
などで確認しましょう。

### microCMSアカウント作成
https://microcms.io/
まずはアカウントを作成してください！
![スクリーンショット 2021-02-05 20.36.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/c9240384-6293-0d5c-86fb-fcb1781c2311.png)
適当にサービスを作成します。
サービス名とサービスIDはなんでもいいです。

その後画像は入れたければ入れて、プランの表示があるので今回はひとまず無料プランで作成します！！

microCMSは無料でもWAF対応やサポートも手厚いのでおすすめです！！

![スクリーンショット 2021-02-05 20.39.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/09a22e88-16e5-ad44-b606-5badd678c30e.png)
登録が完了したらURLをアクセス！！

### APIの作成

![スクリーンショット 2021-02-05 20.41.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/92d54ea8-cac0-0334-e8e7-1e3b9dacf118.png)
今回はblogで作成します。

![スクリーンショット 2021-02-05 20.41.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/e0cf0b33-c7e0-83a0-47b3-308ca36413e8.png)
今回はJSON配列を返却するAPIを作成したいのでリスト形式を選択します！

![スクリーンショット 2021-02-05 20.45.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/c5ea992d-faba-d2ec-6874-e5fa382debf3.png)
次にカラムを設定します！！
ちなみに詳細設定を押すとバリデーションなどが設定できます！

![スクリーンショット 2021-02-05 20.45.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/cf93c1aa-3572-b173-2752-232d287d6073.png)

今回はセレクトフィールドは会社のコーポレートサイトを想定してこんな感じに
![スクリーンショット 2021-02-05 20.44.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/3ac5f43e-c7dc-2b0c-1565-3728d1ce8ad0.png)


###　コンテンツを追加する
今回は簡単に５つくらいコンテンツを作ってみましょう！
追加するでコンテンツが作れます。

![スクリーンショット 2021-02-05 20.50.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/f86ab08b-9192-08e0-a5db-40194d910323.png)
こんな感じで５つくらい作りましょう！

マークダウンが使えるのもエンジニアに優しい、、、
もちろん普通にもかけます。(タイトルのところテキストフィールドに変えてますすいません)

書いたら公開します！

![スクリーンショット 2021-02-05 20.54.26 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/0bb34740-1249-89a1-4b21-42c729c03cae.png)

5つ作るとこんな感じに。

###　API連携
```
cd ~/Desktop/next-js/blog     
touch .env.development.local
```
.env.ファイルを作成します。
next.jsは.env.ファイルはデフォルトでAPIキーを保護します。
間違ってでもgithubにAPIキーをプッシュでもしたら大変なことになるのでしっかり保護しましょう！！

![スクリーンショット 2021-02-05 20.58.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/b4045fda-cf1d-3837-431d-33fd51fb7231.png)

API設定をクリック→APIリファレンスをクリック
![スクリーンショット 2021-02-05 20.59.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/d17118f1-d830-e947-12f9-9b5f6b2f9784.png)
APIキーを表示してコピーします！

```.env.development.local
API_KEY=ここにAPIキーを入れる
```
これで準備は完了です！！

### 一覧ページのデータを取得するデータを取得する

```pages/index.jsx
import Link from 'next/link';

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


export const getStaticProps = async () => {
  const key = {
    headers: {'X-API-KEY': process.env.API_KEY},
  };
  // 自分のIDを入れてください
  const data = await fetch('https://ここは自分のIDを入れる.microcms.io/api/v1/blog', key)
    .then(res => res.json())
    .catch(() => null);
  return {
    props: {
      blog: data.contents,
    },
  };
};
```
IDだけ自分のを入れるのを注意してください！

```
yarn dev
```
http://localhost:3000/
これでひとまずタイトル記事が取得できます！
![スクリーンショット 2021-02-05 21.07.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/9991be29-96d1-e725-21ba-f85a33cea473.png)

説明するとprocess.env.API_KEYでenvファイルのAPIキーを持ってきています

blogにデータの配列が入っているのでそれをmapで返してる感じですね！
今回はtitleにLinkコンポーネントで詳細ページのリンクをつけてます（これから作ります）

getStaticPropsここは超重要ですね。
getStaticPropsはビルド時に静的なファイルを事前に生成するための関数です。
これはクライアントサイドで実行されるってよりかはサーバーサイドで実行されます。
詳しくはSSG, SSR, CSRなどでググってみましょう！！

ちょっと寂しいのでスタイリングしましょうか笑

```
npm install --save sass
```
global.cssをscssに変更して_app.jsの１行目を

```
import '../styles/globals.scss'
```
に変更！！

```global.scss
div {
  width: 70%;
  margin: 0 auto;
  ul {
    margin-top: 100px;
    li {
      border-bottom: 1px solid;
      padding: 50px 0;
      list-style: none;
    }
  }
}
a {
  text-decoration: none;
  color: black;
}
```

![スクリーンショット 2021-02-05 21.23.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/53a212f9-4c24-bc38-a468-8ed112ef0920.png)

### ブログ詳細ページを作成
pages/blog/[id].jsxでファイルを作成します！！
[id]はLinaxでやるとエラー出るかもしれないんで手で作りましょう。

```pages/blog/[id].jsx
import styles from "../../styles/Home.module.scss"

export default function BlogId({ blog }) {
  return (
    <main className={styles.main}>
      <h1 className={styles.title}>{blog.title}</h1>
      <span className={styles.created_ad}>{blog.publishedAt}</span>
      <span className={styles.category}>{blog.category}</span>
      <div className={styles.body}
        dangerouslySetInnerHTML={{
          __html: `${blog.body}`,
        }}
      />
    </main>
  );
}

export const getStaticPaths = async () => {
  const key = {
    headers: {'X-API-KEY': process.env.API_KEY},
  };
  const data = await fetch('https://自分のID.microcms.io/api/v1/blog', key)
    .then(res => res.json())
    .catch(() => null);
  const paths = data.contents.map(content => `/blog/${content.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 data = await fetch(
    'https://自分のID.microcms.io/api/v1/blog/' + id,
    key,
  )
    .then(res => res.json())
    .catch(() => null);
  return {
    props: {
      blog: data,
    },
  };
};
```
またしっかり自分のID入れてください！！
import styles from "../../styles/Home.module.scss"でインポートしています。
Home.module.cssをscssに変更しましょう！！


```Home.module.scss
.main {
  width: 60%;
  margin: 0 auto;
}
.category {
  margin-left: 10px;
  background-color: black;
  color: white;
  padding: 3px 5px;
}
.body {
  margin-right: 400px;
}
```

![スクリーンショット 2021-02-05 21.40.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/63e2cba6-f23a-0560-81e0-127f25d36099.png)

お疲れ様でした！！！

## 番外編
limitで表示される記事を限定する。
今回は５つ記事を作ったので、３つに限定します！！

```index.jsx
import Link from 'next/link';

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


export const getStaticProps = async () => {
  const key = {
    headers: {'X-API-KEY': process.env.API_KEY},
  };
  // この最後のURLにlimitを追加
  const data = await fetch('https://自分のID.microcms.io/api/v1/blog?limit=3', key)
    .then(res => res.json())
    .catch(() => null);
  return {
    props: {
      blog: data.contents,
    },
  };
};
```
https://自分のID.microcms.io/api/v1/blog?limit=3'
URLの最後にlimitをget方式で書くだけです！！
ちなみにデフォルトの件数は10みたいです！

![スクリーンショット 2021-02-05 21.44.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/9d28726f-1b15-5a81-13f7-9c500070af5e.png)

お疲れ様でした！！！

### 参考URL
https://blog.microcms.io/microcms-next-jamstack-blog