この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
こんにちは、今夜のNext.js Conf 2022が楽しみなCX事業本部Delivery部MADグループの森茂です。(執筆時点2022/10/25)
2022/10/24よりCloudflare PagesでNext.jsのEdge Runtimeがサポートされました。
今までは静的なファイルへ書き出されたサイトのみがサポートされていましたが、このアップデートによりNext.jsのEdge Runtimeを利用したEdge環境での動的な処理がサイトで利用できるようになっています。
2022/10/26追記
この記事はNext.js v12.3.1での検証内容となります。Next.js v13ではまだビルドが通らないようでした。
注意が必要な点としては、Cloudflare Workersで動作するEdge RuntimeであるためNode.js環境に依存したものなどライブラリによって動作しない場合があります。Cloudflareの制限というよりはEdge Runtimeの特色となります。そのためNode.js環境で動かしているSSRを利用している既存の環境をそのまま移行ということは難しいかもしれません。
2022/10/24現在 Next.jsのEdge RuntimeはExperimentalとなっています。
ためしてみた
さっそくNext.jsの新規プロジェクトを作成してためしてみます。
$ npx create-next-app@latest sample-app --ts
API Routeへの実装
まずはAPI Routeから実装をためしてみます。
API Routeごとにexperimental-edge
オプションを追加することでEdge Runtimeを利用できます。
export const config = {
runtime: 'experimental-edge',
}
Next.jsのAPI Routeの例
/pages/api/hello.ts
import type { NextApiResponse } from 'next';
export default function handler(
res: NextApiResponse
) {
res.status(200).json({ name: 'John Doe' });
}
Next.js Edge Runtime利用のAPI Route例
/pages/api/hello-edge.ts
import type { NextResponse } from 'next/server';
export const config = {
runtime: 'experimental-edge',
};
export default function handler(es: NextResponse) {
return new Response(JSON.stringify({ name: 'John Doe' }), {
status: 200,
headers: {
'content-type': 'application/json',
},
});
}
従来のAPI RouteとEdge Runtimeでは記述が大きく変わります。Cloudflare Workers等利用されている方には違和感はないと思いますが、Web APIの沿った書き方が必要となってきます。
ServerSideProps
つづけてSSRの動作もためしてみます。
next.config.ts
ファイルに設定を追記することで、ページごとに記載することなくすべてのページを有効化できます。
next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
runtime: 'experimental-edge',
},
reactStrictMode: true,
swcMinify: true,
}
module.exports = nextConfig
Edge Runtimeっぽいロジックは何もないですが、SSRの動作確認のためServerSidePropsからfetchしたデータをSSRするページを用意しておきます。
/pages/index.tsx
import type {
GetServerSideProps,
InferGetServerSidePropsType,
NextPage,
} from 'next';
type Props = InferGetServerSidePropsType<typeof getServerSideProps>;
type Todo = {
userId: number;
id: number;
title: string;
completed: boolean;
};
const Home: NextPage<Props> = (props) => {
const todo: Todo[] = props.todo;
return (
<div>
<h1>Todo</h1>
<ul>
{todo.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
</div>
);
};
export default Home;
export const getServerSideProps: GetServerSideProps = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/todos');
const todo = await response.json();
return {
props: {
todo,
},
};
};
Middleware
つづいてMiddlewareも簡単なものを用意しておきます。レスポンスヘッダーにx-modified-edge
というカスタムヘッダーを追加するというものです。
import { NextResponse } from 'next/server';
export function middleware() {
const response = NextResponse.next();
response.headers.set('x-modified-edge', 'true');
return response;
}
Edge Runtimeで利用できるMiddlewareについては下記に公式のサンプルも多く用意されているので参照ください。
以上で下準備は完了です。
Cloudflare Pagesへのデプロイ
準備ができたところでCloudflare Pagesへデプロイしてみます。あらかじめCloudflareのアカウントとGitHub連携のデプロイをするためリポジトリを用意しておく必要があります。
すでにCloudflare PagesのプロファイルにNext.jsが追加されているので、リポジトリの連携とプロファイルを選択するだけでビルド コマンド
やビルド出力ディレクトリ
には推奨設定が適応されます。
ビルド&デプロイの設定項目 | 設定値 |
---|---|
本番環境のブランチ | main |
ビルド コマンド | npx @cloudflare/next-on-pages --experimental-minify |
ビルド出力ディレクトリ | .vercel/output/static |
なお、Next.jsのデプロイにはNode.js v14以上が必要となります。環境変数でNODE_VERSION
に14以上を設定するか、プロジェクトディレクトリに.node-version
を追加してv14以上のバージョンを指定しおく必要があります。
また、2022/11/30までの限定対応ですが、設定>関数のCompatibility flags
に下記2種類を設定しておく必要もあります。
streams_enable_constructors
transformstream_enable_standard_constructor
詳細については下記公式ドキュメントも参照ください。
動作の確認
準備もできたところでさっそくデプロイして検証してみます。
Middlewareの動作確認
ローカル環境では問題がなかったのですが、Cloudflare Pagesへデプロイした際にレスポンスの中身が空になってしまう現象が発生しページの表示ができなくなってしまいました。付与されるHeaderは追加されているためMiddlewareについては改めて検証してみようと思います。
22/10/26追記
Vercelへ同じソースコードをデプロイしたところVercel上ではMiddlewareの動作に問題なさそうでした。
以降の検証についてはMiddlewareを外した状態で行っています。
API Routeの確認
単にJSONを返すだけですが、問題なさそう。
Server Side Renderingの確認
JSON PlaceHolderから取得したデータがサーバーサイド側で用意されて問題なく返ってきているようです。
さいごに
さわりだけですが、Next.jsのEdge Runtimeに対応したCloudflare Pagesをためしてみました。実際に作り込んでいくとEdge RuntimeというNode.jsと異なった環境とはなるため構成するライブラリによっては動作しないものも数多くあると思います。とはいえコストパフォーマンスの高いCloudflare PagesでNext.jsのSSRやAPI Routeを利用できる選択肢が増えたことはうれしいところです(しかもEdge環境で!)。
KVやR2、DurableObjects、D1との連携も容易となるのでCloudflare Pagesで動作するNext.jsには今までとはまた違った活用法もたくさんありそうですね。