【Qiita API × microCMS】Next.jsでTech Blogを作ってみた

# はじめに
1か月ほど前からNext.jsを学び始めました。
今回はNext.jsでTech Blogを作成してみました。
Qiita APIとmicroCMSに登録したデータを使い、記事を表示させました。
比較的簡単にできたので、興味がある方は参考にしてください。

# Qiita APIと microCMSについて
アプリの紹介をする前に、Qiita APIとmicroCMSについて軽く紹介しておきたいと思います。
知っているという方は飛ばしてもらっても大丈夫です。

## Qiita APIとは
名前から予想できていると思いますが、Qiitaから自分の記事やほかの方が投稿した記事を取得することができます。
また、記事やコメントの投稿もできるようです。
今回はこのQiita APIを使用して、自分の記事を取得します。

https://help.qiita.com/ja/articles/qiita-api

## microCMSとは
microCMSはヘッドレスCMSというもので、よくフロントエンドとは分離したバックエンドの機能を提供するものと言われます。
データを保存したり、取得したりするAPIを提供してくれます。
DBを用意することなく、提供されたAPIのみでバックエンドのデータ取得や保存機能を実現できます。
こちらのmicroCMSに登録したデータをAPIで呼び出してTech Blogの記事表示に使用していきます。

https://microcms.io/features/contents-api

# 開発したTech Blog
基本的にTech Blogなので記事を見たり、記事の一覧をみることができます。

**以下は取得したQiitaの記事を表示しています。**
トップページには最新の4件、もっと見るボタンを押した後の一覧には最新20件の記事を表示しています。

![tech-blog1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1328154/18f0ae22-ff12-111e-527a-16e8d65f5ff5.gif)

**こちらは、microCMSで取得した記事です。**
こちらはトップページには最新4件を表示しており、一覧ページには5件表示しています。（microCMSに5件しかデータを登録していないため）

![tech-blog2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1328154/eacb82d7-9b2c-70bd-1c45-528d0ee2652e.gif)

# 開発言語とツール
言語はタイトルにもある通り、Next.jsを使用しており、TypeScriptも使っています。
UIに関してはTailwind CSSを使っています。
開発効率のためにCICDを組んでいます。Github Actionsでmainにpushされた際、build, test, deployの一連の流れを実行するように設定しています。

また、deploy先ですが、Firebase Hostingを使用して、ページをどこからでもアクセスできるようにしました。

| 名前 | 説明 |
|:-:|:-:|
| **使用言語**  | Next.js, TypeScript  |
| **UI**  | [Tailwind CSS](https://tailwindcss.com/) |
| **CICD**  | GithubActions |
| **サーバーサイド** | [Firebase](https://firebase.google.com/?hl=ja) |

## Next.jsでTech Blogを開発してみて成長したところ
Next.jsはReactのフレームワークです。
今は当たり前に理解していますが、Next.jsを見聞きしたことがあるぐらいの時は「Next.jsってNode.jsみたいなもの？」と認識していました。
全く、Next.jsについて知らなかったです。

今回そんなNext.jsでTech Blogを開発してみて、以前より成長したと実感したことは

- ReactのフレームワークとしてのNext.jsの立ち位置の理解
    - サーバーサイドの理解
    - CSR, SSG, SSR, ISR

です。

**この「ReactのフレームワークとしてのNext.jsの立ち位置の理解」について詳しく話していきます。**

Reactがあるのに、なぜNext.jsが必要なのか。

私はNext.jsを触る前ははっきりと理解していませんでした。Reactを使用して、大抵のアプリは作ってこれました。
特に、React意外を使わないと作れないとは感じませんでした。

じゃあなぜ、Next.jsがあるのか。
私が今まで作ってきたアプリは多くの人が触れるものではありませんでした。なので、サーバー負荷やレンダリング速度もそこまで気にならなかったです。
ただ、これが多くの人が触れるアプリとなると多数の人にできるだけ遅延なくページを表示して上げないといけません。
そこで、Next.jsのSSG, SSR, ISRによって、レンダリングをページごとに調整することによって、ページを見る人へ遅延なく届けることができます。また、ReactはCSRなのでシークレットキーを設定していたりすると、閲覧者がそのキーを見ることができます。

これは実際に作ってみて、どういう仕組みとなっているか理解したことで、Next.jsの役割が分かってきました。
**Next.jsの役割について理解し、サーバーサイドのレンダリング方法について理解できたことが大きな収穫であり、自分のエンジニアとしての成長につながりました。**

最近React v19がでてきましたが、サーバーサイドの機能でどのようなものが必要か理解しておけば、Next.jsでもそうでなくても根本となる仕組みは変わらないと感じました。

大事なのは、理解して使いこなすことだと思います。

# Tech Blogを開発してみて、大変だった点
大変だった点は、Reactとの差異とNext.jsをFirebaseにデプロイすることでした。

## Reactとの差異
まず、Reactとの差異ですが、Next.jsではサーバーサイドでレンダリングする場合、useStateやuseEffectを使用することはできません。
```tsx
import React, { useEffect, useState } from "react";
import { QiitaBlog } from "../types/qiitaBlog";
import QiitaCard from "../components/QiitaCard";

const Page = () => {
  const [qiitaItems, setQiitaItems] = useState<QiitaBlog[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/qiita`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ page: 20 }),
        });
        const data: QiitaBlog[] = await res.json();
        setQiitaItems(data);
      } catch (error) {
        console.error("Error fetching data:", error);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []);
```

これらを使おうとするとエラーになってしまいます。
そのため、useState、useEffectを使用せずこのように定義する必要があります。
```tsx
import React from "react";
import { QiitaBlog } from "../types/qiitaBlog";
import QiitaCard from "../components/QiitaCard";

export const dynamic = "force-dynamic";
export const fetchCache = "force-no-store";

const page = async () => {

  const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/qiita`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ page: 20 }),
  });
  const qiitaItems: QiitaBlog[] = await res.json();

```

もし、useStateやuseEffectをどうしても使いたいならばCSRにすることで使用することが可能です。
CSRにする方法は簡単でこのように`"use client"`を頭につけます。
```tsx
"use client"

import React from "react";
import { QiitaBlog } from "../types/qiitaBlog";
import QiitaCard from "../components/QiitaCard";
```

これ以外にも、APIをGetでfetchする際に、SSG, ISRで取得するということを明示的に示さないといけません。
以下参考記事

https://zenn.dev/bizlink/articles/f86df042197cbd

これらのReactとの違いに最初は悩まされました。

## Firebaseへのデプロイ
Next.jsのデプロイはうまくデプロイできなかったり、ページが表示されなかったりと結構時間をとられました。

Reactであれば、初期設定後に`firebase deploy`を実行すれば、問題なくデプロイされたのですが、
Next.jsの場合は`firebae deploy`を実行してもエラーがでてうまくデプロイできませんでした。

https://qiita.com/shinry/items/a649d923b799828c4ecc

また、デプロイができても、ページが真っ白になってしまう事象が発生しました。
原因としてはenvのキーの値がローカルと本番で異なっていたため発生したものでした。

https://qiita.com/shinry/items/0db8e96e5f8a06257652

新しいことを始めると一筋縄ではいきませんが、その分たくさんのことを学べます。

# 新しいことを学ぶ楽しさ
今回Next.jsでアプリを作ったり、Qiita APIやmicroCMS等の触ったことがない技術に触れました。

やはり新しいことを学ぶのは時間もかかり大変ですが、あらたな知見や発見をすることができ、またこれもできるようになったという自信もつきます。

新しいことを学ぶのは楽しいと再度実感しました。

# おわりに
最後まで読んでくださった方ありがとうございます。
今回はNext.jsで簡単なアプリを作ってみました。これからも色々開発して共有していきたいと思います。
この記事がどなたかの役に立てば幸いです。

# JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？

気になる方はぜひHPからお願いします👇

https://projisou.jp