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

发表评论 取消回复