個人サイトを Next.js から Vite + React に移した
個人サイトを 3 年近く Next.js(+ Linaria, Cloudflare Pages, Workers)で開発してきたのですが、この度使い慣れた Vite + React に移行することにしました。主な理由は以下の通りです。
- Vercel 以外の環境(特に Cloudflare 等の Edge Runtime)との相性が悪い
- 相性の悪いライブラリが多い
- そもそも個人サイトなので SEO や速度に拘る必要がない
- App Router 周りの不安定さ
やったこと
Next.js 固有の機能の移行
ルーティング周りは鉄板のreact-router-dom に移行しました。若干ハマった点として、/public
配下の静的ファイルに遷移する際は Link コンポーネントの reloadDocument
属性を付与する必要があります。サイト内ではリンクに統一したコンポーネントを採用しているため、以下の通りに記述しています。
if (href.startsWith("https://") || href.startsWith("http://")) {
return <a href={href}>{content}</a>;
}
if (href.endsWith(".pdf") || href.endsWith(".xml") || ...) {
return <Link to={href} reloadDocument>{content}</Link>);
}
return <Link to={href}>{content}</Link>;
その他は基本的に基のコンポーネントをコピーしつつ、next/head を react-helmet-async に移したり、searchParams の処理を若干書き換えたりしました。一部 SSR で fetch していたページに関しては、純粋に useEffect 内にその処理を移しました。Next.js に固有の機能をそれほど使っていなかったため、移行は楽に感じました。
RSS フィード
API Routes から feed パッケージを呼び出すことで RSS/Atom/JSON フィードを SSG してきましたが、以下のスクリプトを用いてビルド時に json および xml を生成するように変更しました。また Cloudflare ではなく GitHub Actions 側でビルドを行い、生成されたファイルを Cloudflare Pages に直接デプロイ[1]するように変更しました。これにより、2 分半以上掛かっていたビルドが 30 秒程度まで短縮されました。同様の仕組みを用いれば OGP の生成等も実現できそうです。
import fs from "node:fs";
import { Feed, type FeedOptions } from "feed";
import { articleLinks } from "../src/app/articles/articles";
const feed = new Feed(feedOptions);
for (const link of articleLinks) {
feed.addItem({
title: link.title,
description: "",
date: new Date(link.date),
id: link.href,
link: link.href,
});
fs.writeFileSync(`${path}/feed.xml`, feed.rss2());
fs.writeFileSync(`${path}/atom.xml`, feed.atom1());
fs.writeFileSync(`${path}/feed.json`, feed.json1());
おわりに
Webpack や Babel が一掃され開発体験が上がったのは嬉しい限りです。SSR と比較すると、DB から動的にコンテンツを取ってくる処理はやはり若干の遅延を感じますが、概ね問題ないレベルだと思われます。
移動記等、一部移せていないページがあるので、今後はそうした箇所も移行させつつ、認証部分(現状は GitHub OAuth)へのパスキーの導入等にも注力していきたいです。
-
CF Pages のビルド制限が 500 回/月というのは CF 側でビルドを一切行わない場合にも適用されるのかが気になっている ↩︎