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

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部