Cloudflare 内部のネットワークを利用するので高速に処理可能です
動作確認環境
Next.js 14.2.13 (App Router)
Edge Runtime は非常に便利な機能ですが Node Runtime の fs 等を使うことができず、ファイルの読み込みが難しいです
前回は、以下でかなりゴリ押しな方法を紹介しました
require を利用したかなり厳しめのファイルインポート方法
そのほか通常の Fetch API を利用することも可能ですが、同じサーバ内に静的リソースが保存されていて Cloudflare Pages にデプロイしている場合は、Cloudflare が提供する fetch を利用することが可能です
この fetch は Cloudflare ネットワーク内で完結するため Cloudflare がよしなに安全で高速に処理してくれます
なんと、その fetch は、環境変数に格納されているためそこから呼び出します (ちょっと気持ち悪いですが...)
TypeScript 環境であれば、まずは型定義をしておきます
@types/node を npm で導入の上、以下のように env.d.ts をプロジェクトルートに配置しておくと良いと思います
declare global {namespace NodeJS {interface ProcessEnv{ASSETS?: {fetch: (input: RequestInfo, init?: RequestInit) => Promise<Response>},[index: string]: string}}}export {}
Next.js の場合は、画像やテキストなど、アクセスする静的リソースは public ディレクトリに保存します
例えば public/text.txt というファイルを取得したい場合は、以下のようにします
export const runtime = 'edge'export default async () => {const url = new URL('https://example.com/text.txt') // 相対パスだとエラーconst res: Responce = await process.env.ASSETS!.fetch(url)const text = await res.text()return <div>{text}</div>}
URL は絶対パスで指定する必要がありますが、開発環境などでも利用したい場合は、動的に URL を取得します
そのままでは取得できないので middleware でヘッダに X-Url を付与して難をしのぐことにします
以下は middleware.ts です
import { NextResponse, NextRequest } from 'next/server'export const runtime = 'experimental-edge'export const middleware = async (req: NextRequest) => {// リクエストヘッダにアクセスのあった URL を付与するconst requestHeaders = new Headers(req.headers)requestHeaders.set('X-Url', req.url)return NextResponse.next({headers: requestHeaders,})}
これを Edge Runtime を利用しているページで取得します
import { headers } from 'next/headers'export const runtime = 'edge'export default async () => {const original_url = new URL(headers().get('X-Url')!)const url = new URL(`${url.origin}/text.txt`) // 相対パスだとエラーconst res: Responce = await process.env.ASSETS!.fetch(url)const text = await res.text()return <div>{text}</div>}
これで高速なリソースアクセスが可能になりました 🎉
手元で計測したところ、初回の fetch だけは 40ms 程度かかっていましたが、それ以降は 0 ms でした
Edge Runtime は実行時間に制限があったりするので、かなり重宝します
おわりに
この fetch でアクセスするリソースについては Cloudflare Access や Next.js の middleware を通過しない (パス状態) ことに注意してください 🐶
Middleware を利用する方は、無駄なエッジ使用を減らすために、こちらの記事も参考にどうぞ ⭐