Next.js 15 与 Edge Databases(Cloudflare D1/Neon/Supabase)一体化实践概述边缘数据库让数据就近可用,结合 Next.js 15 的 RSC/PPR 与缓存标签,实现既快又一致的数据层。本文给出 D1/Neon/Supabase 的接入、读写与失效治理。Cloudflare D1 集成// wrangler.toml(绑定数据库) [[d1_databases]] binding = "DB" database_name = "appdb" database_id = "<id>" // app/api/d1/route.ts(边缘 Route Handler) import { NextResponse } from 'next/server' export const runtime = 'edge' export async function GET(req: Request) { // @ts-ignore Cloudflare 环境注入 DB const db = (globalThis as any).DB as D1Database const { results } = await db.prepare('SELECT id, title FROM posts ORDER BY id DESC LIMIT 20').all() return NextResponse.json(results, { headers: { 'Cache-Control': 'public, max-age=60' } }) } Neon Serverless Postgres 集成// neon.ts(边缘连接) import { neon } from '@neondatabase/serverless' export const sql = neon(process.env.NEON_DATABASE_URL!) export async function listPosts() { return sql`SELECT id, title FROM posts ORDER BY id DESC LIMIT 20` } // app/api/neon/route.ts import { NextResponse } from 'next/server' import { listPosts } from '@/neon' export const runtime = 'edge' export async function GET() { const rows = await listPosts() return NextResponse.json(rows, { headers: { 'Cache-Control': 'public, max-age=60' } }) } Supabase 边缘读取(RLS 开启)// supabase.ts import { createClient } from '@supabase/supabase-js' export const supabase = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.SUPABASE_ANON_KEY!, { auth: { persistSession: false } }) export async function getUserPosts(userId: string) { const { data, error } = await supabase.from('posts').select('id,title').eq('user_id', userId).order('id', { ascending: false }).limit(20) if (error) throw error return data } Server Actions 写入与缓存标签// app/actions.ts 'use server' import { revalidateTag } from 'next/cache' import { sql } from '@/neon' export async function createPost(formData: FormData) { const title = String(formData.get('title') || '') if (!title) return { ok: false, error: 'Title required' } await sql`INSERT INTO posts (title) VALUES (${title})` revalidateTag('posts') return { ok: true } } RSC/PPR 与 `unstable_cache`// app/posts/page.tsx import { unstable_cache } from 'next/cache' export const dynamic = 'force-static' const getPosts = unstable_cache(async () => { const res = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/neon`, { next: { tags: ['posts'] } }) return res.json() }, ['posts'], { revalidate: 300 }) export default async function PostsPage() { const posts = await getPosts() return ( <main> <h1>Posts</h1> <ul>{posts.map((p: any) => <li key={p.id}>{p.title}</li>)}</ul> </main> ) } 一致性与区域策略D1:单区域写入+多区域读取;Neon:就近路由与无连接池;Supabase:RLS 与 JWT 作用域隔离失效:统一使用 `tags: ['posts']`,写入后 `revalidateTag('posts')`技术参数与验证Node.js 20.x;浏览器 Chrome 120+D1/Neon/Supabase 三平台联调:列表命中率 > 80%;首屏 LCP 1.9-2.4sRoute Handlers 边缘响应延迟:D1 3-8ms(边缘)、Neon 20-40ms(就近)、Supabase 25-60ms(RLS)应用场景全球分发内容站点(读多写少)就近读取的交互型站点(读写均衡,Neon/Supabase)注意事项环境变量与密钥隔离;避免在客户端暴露 `service_role`边缘运行时限制:仅使用兼容的 SDK(Neon serverless,Supabase JS 无 Node-only 特性)常见问题Q: 多平台并存是否复杂?A: 通过统一标签失效与接口抽象,降低耦合。参考资料Cloudflare D1 文档Neon Serverless 文档Supabase 文档(RLS、Edge 集成)---发布信息:已发布 · 技术验证 · 阅读 42 分钟 · CC BY-SA 4.0

发表评论 取消回复