Cloudflare Pages

git integration
-
github or gitlab
-
project name
がhostname
になる -
production branch
を指定main
とかmaster
- 事前にgithubに
main
ブランチとかがないとダメ -
それ以外の全てのブランチ
=preview deployment
で使われる
- 事前にgithubに
-
ビルド設定
- 必須
build command
- 必須
build output directory
- オプション
- ルートディレクトリ。default=リポジトリルート
- 環境変数
- 必須
-
DNSエラー発生するかも
wait for the DNS to propagate
-
Cloudflare Pages dashboard
- Deployment, ..., Settingsのタブ UI
-
削除
- Settings > delete project
- CNAMEレコードを先に消さないと削除できない

@cloudflare/next-on-pages
-
@opennextjs/cloudflare
- workersにnext.jsをビルド・デプロイできる
- Node.js API が一部可
- OpenNext document

Get Started
# 新規
npm create cloudflare@latest -- my-next-app --framework=next
# 既存app
npm install --save-dev @cloudflare/next-on-pages
# wrangler.toml追加
touch wrangler.toml
# next.configへの追記
code ./next.config.mjs
wrangler.toml
- https://developers.cloudflare.com/pages/functions/wrangler-configuration/
- project設定を宣言的に記述したもの
- bindings が参照
-
name = "my-app" compatibility_date = "2024-07-29" compatibility_flags = ["nodejs_compat"] pages_build_output_dir = ".vercel/output/static"
next.config.追記(bindings利用に必須)
++ import { setupDevPlatform } from '@cloudflare/next-on-pages/next-dev';
// skip
/** @type {import('next').NextConfig} */
const nextConfig = {
// skip
};
++ if (process.env.NODE_ENV === 'development') {
++ await setupDevPlatform();
++ }
export default nextConfig;
Pagesでは edgeランタイムを指定
- Next.jsは2つランタイムをサポート:
Edge
orNode.js
- 手順:
getServerSideProps()
使ってる全ファイル、api routesの全ファイルに1行追記-
export const runtime = "edge";
-
package.json
にnpm scripts追記
// next build実行プラス、pages互換な形に変換
++ "pages:build": "npx @cloudflare/next-on-pages",
// wrangler pages dev = OSSのworkerランタイムでローカル実行
// next devは Node.jsランタイムでの実行
++ "preview": "npm run pages:build && wrangler pages dev",
// ビルド後にデプロイ実行
++ "deploy": "npm run pages:build && wrangler pages deploy"
デプロイ
- automatic deoployment: pushしたらデプロイ
- CLIで手動デプロイ:
wrangler pages deploy
専用のeslintプラグイン
npm install --save-dev eslint-plugin-next-on-pages
{
"extends": [
"next/core-web-vitals",
++ "plugin:eslint-plugin-next-on-pages/recommended"
],
"plugins": [
++ "eslint-plugin-next-on-pages"
]
}

Bindingの活用
getRequestContext()
- bindingsにアクセスできる
const { env, cf, ctx } = getRequestContext();
ts対応
install, tsconfig
, env.d.ts
# インストール
npm install --save-dev @cloudflare/workers-types
# tsconfigのtypesに追記
code tsconfig.json
# binding データの型定義
touch env.d.ts
"types": [
++ "@cloudflare/workers-types/2024-07-29"
]
interface CloudflareEnv {
MY_KV_1: KVNamespace;
MY_KV_2: KVNamespace;
MY_R2: R2Bucket;
MY_DO: DurableObjectNamespace;
}
cf
, cfx

workerエントリポイント
- pagesのrouteへのreq/resに処理を挟める。middlewareライク
- workerに類似
- workerと違う
-
wrangler.toml
が不要 - Pagesプロジェクトの一部としてdeployされる
-
- https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/
// 構成
import nextOnPagesHandler from "@cloudflare/next-on-pages/fetch-handler";
export default {
async fetch(request, env, ctx) {
// do something before running the next-on-pages handler
const response = await nextOnPagesHandler.fetch(request, env, ctx);
// do something after running the next-on-pages handler
return response;
},
} as ExportedHandler<{ ASSETS: Fetcher }>;
# Q:automatic deploymentはこれで動くのか
npx @cloudflare/next-on-pages --custom-entrypoint=./custom-entrypoint.ts

Caching、Revalidation
- pagesではデータのcachingとrevalidatingをサポート
- (WHATWGの)
fetch()
経由のサブリクエストは全てキャッシュされる - https://developers.cloudflare.com/workers/runtime-apis/fetch/
- デフォルトのキャッシュの挙動を無効にすることは可能
- デプロイを繰り返してもキャッシュは永続化される。
- 手動でrevalidate or purgeをする必要あり
- https://nextjs.org/docs/app/building-your-application/caching#data-cache
- キャッシュの保存先は2種類:worker KV か Cache API
- worker KV(推奨)
- https://developers.cloudflare.com/kv/
- 結果整合性(eventually consistent)
- 60sec必要(グローバルに反映されるのに)
- 有効化手順
- KV bindingをtomlに追加
- https://developers.cloudflare.com/pages/functions/bindings/#kv-namespaces
-
__NEXT_ON_PAGES__KV_SUSPENSE_CACHE
にbinding名をセット
- KV bindingをtomlに追加
- Cache API(デフォルト)
- https://developers.cloudflare.com/workers/runtime-apis/cache/
-
when you write data using the Cache API, data is only cached in the Cloudflare location that you are writing data from
- worker KV(推奨)

Static Assets
worker実行をスキップして静的アセットを返却する
-
routes.json
-
@cloudflare/next-on-pages
が自動生成- ビルド時に生成される
- 手動作成=NG
- https://developers.cloudflare.com/pages/functions/routing/#create-a-_routesjson-file
- workerを実行せずに静的アセットを返せ、という指定
-

@cloudflare/next-on-pages
がサポートする機能
-
ごく一部のNode.js API
-
buffer
,events
,assert
,util
,async_hooks
- https://github.com/vercel/next.js/blob/canary/packages/next/src/build/webpack/plugins/middleware-plugin.ts#L820
-
-
Router: App router, pages router両方
-
Next.jsのi18n routing
-
ISRのフォールバック
- SSGのようにビルドが走る
- ISRサポートされない理由: VercelのPrerender Functionがpagesとedge runtimeで動かない
- https://vercel.com/docs/build-output-api/v3/primitives#prerender-functions
-
ISR pages are built by the Vercel CLI to generate Vercel Prerender Functions
-
Dynamic handling of static routes
-
@cloudflare/next-on-pages supports standard statically generated routes.
It does not support dynamic Node.js-based on-demand handling of such routes.
-
-
caching, revalidation
サポートしない機能
- Node.js API
-
@opennextjs/cloudflare
を使え。ただしメジャーリリース前 -
v1.0
リリース後はこちらが推奨になる- Next.jsの新機能は
Node.js
APIを前提にしてるため
- Next.jsの新機能は
-

pages router使用時のランタイム指定
-- export const runtime = "edge";
++ export const runtime = 'experimental-edge';
not-found
routeでのエラー対策
- Next.jsが自動生成する
not-found
routeのかわりに自作 - 自動生成される
not-found
route- Node.jsランタイムを前提にしたサーバレス関数
- https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes
export const runtime = 'edge'
export default async function NotFound() {
// ...
return (
// ...
)
}
-
SSGで、
generateStaticParams()
を/app
以下で使うとエラーに =>dynamicParams
をfalse
に- Node.jsランタイム向けにサーバレス関数が作成されてしまうため
-
トップレベル
getRequestContext()
はNG -
SSGで
/pages
以下でgetStaticPaths()
でエラー =>fallback: false,
に

-
推奨しない手順についてのページ:SSR(Full Stack)が推奨
-
static export利用時
npx create-next-app --example with-static-export my-app