Next.js + microCMSでポートフォリオっぽいものを作る
想定環境
- Next.js: 最近フロントエンドの勉強として触り始めて楽しいので
- microCMS: 都度更新するコンテンツについてはここで追加していく
- vercel or github pages: デプロイ先は検討中。ポートフォリオを目指して作るならgithubでまとめて管理したい気持ちはある
載せたいコンテンツ
- 自己紹介
- 学習記録(自らへの戒めを込めて)
- 映画、本の記録(ただAPIとかの勉強がてら載せたいのと、趣味なので)
- その他思いついたら都度追加
技術的に達成したいこと
- Next.jsでイチからなにか作れるようになる
- 自動テストをかけるようになる
- CI/CDについて理解する
vercelかgithub pagesかという点で、今回はgithub pagesを採用したい
- Next.jsのApp Routerを存分に使ってみたい
- github pagesは静的サイトしか扱えないので↑の制約はあるが、目的としてるサイトではそこまで影響なさそう
- github actionsを使ってみたい
参考
Unsupported Features
Features that require a Node.js server, or dynamic logic that cannot be computed during the build process, are not supported:
Dynamic Routes with dynamicParams: true
Dynamic Routes without generateStaticParams()
Route Handlers that rely on Request
Cookies
Rewrites
Redirects
Headers
Middleware
Incremental Static Regeneration
Image Optimization with the default loader
Draft Mode
GitHub Docs - GitHub Pages について
GitHub Pages は、リポジトリにプッシュされたあらゆる静的ファイルを公開します。
Next.js 14をgithub pagesで公開する
プロジェクトの作成 && SSG用設定
とりあえずお決まりのコマンドでnext.jsのプロジェクトを作る
npx create-next-app@latest .
SSG用にconfigファイルを書き換える
/** @type {import('next').NextConfig} */
const nextConfig = {
output:'export',
};
/* module.exports = nextConfig*/
export default nextConfig;
githubでgithub pages用のリポジトリを作る
- リポジトリ名は「[ユーザ名].github.io」で作る
- プロジェクトをリポジトリにプッシュ
github pagesの設定を行う
こちらを参照
ymlファイルの書き換え
こちらを参考にymlファイルの以下をすべてコメントアウト
- name: Setup Pages
uses: actions/configure-pages@v4
with:
# Automatically inject basePath in your Next.js configuration file and disable
# server side image optimization (https://nextjs.org/docs/api-reference/next/image#unoptimized).
#
# You may remove this line if you want to manage the configuration yourself.
static_site_generator: next
- name: Static HTML export with Next.js
run: ${{ steps.detect-package-manager.outputs.runner }} next export
変更をCommitしたら自動でデプロイが始まるので完了まで待つ
確認
リポジトリのSetting>Pages>Visit SiteでNextjsのTOPページが表示されたらOK
余談
14で同じようなことをしている日本語記事が無かったのと、Actionsを初めて触ってので少し手こずった。
discussionありがたい🙏
ちなみに、github actionsのエラーについて、
static_site_generator: next
これがあるとconfigが上書きされちゃうらしい
next export
これはnextjs14で廃止、output:'export',を指定しておけばnext buildでoutの出力までされるのでコメントアウトでOK
microCMSの環境変数にgithub actionsからアクセスできるようにする
github actionsでnextjsデプロイ時に環境変数が取得できずビルドエラーが発生
以下の対応を実施
1. githubに環境変数を追加
settingから環境変数を追加
settings > environments > github-pages > Add secretで必要な環境変数を追加
2. github actionsで.envファイルを作成
ymlファイルに以下の記述を追加
build:
runs-on: ubuntu-latest
environment: # ←これ
name: github-pages # ←これ
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create .env file # ←これ
run: | # ←これ
echo "MICROCMS_API_KEY=${{ secrets.MICROCMS_API_KEY }}" >> .env # ←これ
echo "MICROCMS_SERVICE_DOMAIN=${{ secrets.MICROCMS_SERVICE_DOMAIN }}" >> .env # ←これ
トレイリングスラッシュについて
SSGの場合、デフォルトだとトレイリングスラッシュありのURLにアクセスすると404になる
以下を追加してトレイリングスラッシュありの場合でもページにアクセスできるようにする
const nextConfig = {
output:'export',
trailingSlash: true, // 追加
};
ブログ記事のパーマリンクについて
まさにこの問題(未解決)
現状
microCMSから記事詳細を取得する際には記事ごとに発行されるユニークidをキーにリクエストする必要がある。そのため、 記事詳細のリンクを/[id]
とし、generateStaticParamsでそのidでページを生成し、paramsのidを取得して記事内容を取得している
export async function generateStaticParams() {
const posts = await client.get({ endpoint: "blog" });
return posts.contents.map((post: Blog) => ({
id: post.id,
}))
}
export default async function Post({ params }: { params: { id: string } }) {
const post: Blog = await getData(params.id);
...(記事内容の出力処理)
やりたいこと
SEO的にランダムな文字列をパーマリンクとすることは微妙なので、できれば自分が指定したパーマリンクを生成し、idは裏側で受け渡して記事内容を取得できるようにしたい
問題
SSGにおいてgenerateStaticParamsはルーティングのためのparamsを生成することしかできないので、独自のパーマリンクを追加のparamsとして加えることができない
↓こんな感じのことをしたい
export async function generateStaticParams() {
const posts = await client.get({ endpoint: "blog" });
return posts.contents.map((post: Blog) => ({
parmalink: post.parmalink, // /[parmalink]としてURLを生成
id: post.id, // idをparamsとして渡して記事詳細を取得
}))
}
export default async function Post({ params }: { params: { id: string } }) {
const post: Blog = await getData(params.id);
対応
今のところ解決策が見つからないのと、個人ブログでアクセス数をあまり気にしていないので一旦対応を見送る
最上位のタグが不要でkeyを指定したい場合
パンくずリストの一部をmapを使って出力していたが、keyを指定していないためにWarningが発生
{segments.map((segment, key) => {
joinedSegment += segment + "/";
display = key === 0 ? segment.charAt(0).toUpperCase() + segment.slice(1) : segment;
return (
<>
<BreadcrumbSeparator />
<BreadcrumbItem key={key}>
{key < segments.length - 1
? <BreadcrumbLink href={`/${joinedSegment}`}>{display}</BreadcrumbLink>
: <BreadcrumbPage>{display}</BreadcrumbPage>
}
</BreadcrumbItem>
</>
);
})}
Fragmentの省略記法(<>)ではkeyを指定できないので、明示的に<Fragment>としてkeyを追加する
{segments.map((segment, key) => {
joinedSegment += segment + "/";
display = key === 0 ? segment.charAt(0).toUpperCase() + segment.slice(1) : segment;
return (
<Fragment key={key}> {/* ここ */}
<BreadcrumbSeparator />
<BreadcrumbItem key={key}>
{key < segments.length - 1
? <BreadcrumbLink href={`/${joinedSegment}`}>{display}</BreadcrumbLink>
: <BreadcrumbPage>{display}</BreadcrumbPage>
}
</BreadcrumbItem>
</Fragment> {/* ここ */}
);
})}
microCMSの記事一覧が更新されない
github actionsでデプロイが完了してもmicroCMSで追加した記事が更新されない
nextjsのcacheが効いているせいで過去のデータを持ってきているよう
github actionsでbuildコマンドを流す前にcacheファイルを削除する
- name: Install dependencies
run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
- name: Remove cache files # 追加
run: rm -rf .next/cache/fetch-cache # 追加
- name: Build with Next.js
run: ${{ steps.detect-package-manager.outputs.runner }} next build