Next.js と ecforce の API で超速い EC サイトを作ってみた
Next.js のパフォーマンス関連の機能を使えば、ダイナミックなウェブアプリを静的ウェブアプリのようにスピーディに表示することができます。今回は、実際にパフォーマンス機能の検証を行った際の事例をご紹介します。
▼ デモアプリはこちら
https://ecforce-headless.vercel.app
なぜパフォーマンスが重要なのか
もちろんユーザ体験のためでもありますが、それだけではありません。「Core Web Vitals」 は Google の検索ランキングにも影響するので、パフォーマンス改善は SEO のためにもなります。EC サイトに SEO がどれだけ重要かは言うまでもないですね。
実現方法
キャッシュ
Next.js の unstable_cache
機能を使って、ホームページの動的コンテンツをキャッシュしています。こうすることで、ビルドの時点で静的ページとしてプリレンダリングされ、商品情報に何らかの更新があれば、自動的にキャッシュクリアもできます。
const getMainProducts = unstable_cache(
async () => {
const products = await ecforceApi.admin.products.list();
const filteredProducts = products.slice(0, 4);
return filteredProducts;
},
undefined,
{
tags: ["products"],
}
);
商品詳細の場合も、商品詳細を取得する関数をキャッシュしています。
const getProduct = unstable_cache(
async (id: string) => {
try {
return await ecforceApi.admin.products.get(id);
} catch (error) {
if (error instanceof NotFoundError) {
return null;
}
throw error;
}
},
undefined,
{
tags: ["products"],
}
);
ecforce の Webhook 機能を使って、商品情報が更新されたときにキャッシュをクリアすることもできます。
import { revalidateTag } from "next/cache";
import { headers } from "next/headers";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
const PRODUCT_EVENTS = [
"product_created",
"product_updated",
"product_destroyed",
];
export async function POST(req: NextRequest) {
// TODO: Check webhook secret to avoid access from random users.
const topic = (await headers()).get("x-ecf-event") || "unknown";
const isProductUpdate = PRODUCT_EVENTS.includes(topic);
const body = await req.json();
console.log(`Received webhook for topic: ${topic}`, body);
if (!isProductUpdate) {
// We don't need to revalidate anything for any other topics.
return NextResponse.json({ status: 200 });
}
if (isProductUpdate) {
revalidateTag("products");
}
return NextResponse.json({ status: 200, revalidated: true, now: Date.now() });
}
ecforce の管理画面から「設定 > Webhook 管理 > 商品 Webhook 管理」 で Webhook を設定しました。( Webhook 機能を使いたい場合、別途オプションを申し込む必要があります。)
プリフェッチ
Next.js は、自動的に画面上に表示されているリンクの静的コンテンツをプリフェッチします。さらに、Link
コンポーネントに prefetch={true}
を設定することも可能です。これにより、Next.js はページ全体をプリフェッチし、動的部分も含めて即時のナビゲーションを実現できます。動的部分のローディングは表示されません。
<Link prefetch href={`/products/${product.id}`}>
...
</Link>
画像プリフェッチ
画面遷移を更に高速化するために、リンクホバー時にターゲット画面の画像をプリフェッチすることもできます。こちらのトリックは NextFaster プロジェクトから採用されました。主に確認すべきコードは、prefetch-images
の API ルートとカスタムの link.tsx
のコンポーネントです。
結論
EC サイトは固定のコンテンツが多くあるので、それらをNext.js のキャッシュ機能を使って高速化させることができます。よくアクセスされるコンテンツも基本的にはキャッシュされるので、サーバーの負荷も軽減され、キャンペーン時などの大量アクセスにも対応しやすくなります。パフォーマンスの改善は、SEO にも影響するので重要です。
プリフェッチと画像プリフェッチのトリックも使えば、高速でスムーズな体験を提供できますが、その分無駄なリクエストも増えるので、ホスティングサービスのコストも増えるかもしれません。プリフェッチ機能は、使いどころを考えて使うことが重要だと思います。
Discussion