-
使用
server action来处理form表单的文件上传的时候,出现文件名乱码的情况,无论怎么修都修不好,后面换成了API route的方式
原因:Server Actions 对 multipart/form-data 里的文件名编码解析错误,官方至今没有完全修复
-
我当时,使用了Prima 的最新版本
V7.x,但Next使用的是V14,比较低的版本,结果一直没有连上。后面知道Prisma与Next版本、Node版本有对应关系,改了版本,就好了。
老项目(13/14) :锁 Prisma 5–6。稳定主力(15) :Prisma 6.x 最稳,新项目(16) :直接上 Prisma 7.x + Node 22。
-
Next.js 深度解析:解决 "next/headers 只能在 Server Components 中使用" 的最佳实践
问题背景
最近在开发 Next.js 项目时,遇到了一个令人困惑的错误:
Ecmascript file had an error
You're importing a component that needs "next/headers". That only works in a Server Component which is not supported in the pages/ directory.
这个错误出现在我使用 Supabase SSR 客户端时,具体代码如下:
// lib/supabase/server.ts
import { createServerClient } from "@supabase/ssr"
import { cookies } from "next/headers" // 👈 这里出错了
export async function createClient() {
const cookieStore = await cookies()
// ...
}
错误原因分析
错误的核心在于 next/headers 模块只能在Server Components 中使用。但从调用栈来看,我的 server.ts 文件被多个地方引用:
- Server Components(服务器组件)
- Client Components(客户端组件)
- Client Component SSR(客户端组件服务端渲染)
这意味着我试图在一个共享文件中使用只能在服务器端工作的 API,这显然是行不通的。
解决方案
经过多种尝试后,我采用了条件渲染的方案,根据运行环境返回不同的客户端:
import { createServerClient } from "@supabase/ssr"
import { createBrowserClient } from "@supabase/ssr"
export async function createClient() {
// Server Component: create client with cookie support
if (typeof window === 'undefined') {
const cookieStore = await import("next/headers").then(cookies => cookies.cookies())
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return cookieStore.getAll()
},
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) => cookieStore.set(name, value, options))
} catch {
// The "setAll" method was called from a Server Component.
}
},
},
}
)
}
// Client Component: create client without cookie support
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
}
export function createServerSideClient() {
// Only for server components (no cookie handling needed for server-only operations)
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return []
},
setAll() {
// No-op for server-only operations
},
},
}
)
}
解决方案的优点
-
保持向后兼容:现有代码基本不需要修改
-
符合 Next.js 最佳实践:
- 服务端组件:使用
next/headers处理 cookies - 客户端组件:使用
createBrowserClient不依赖 cookies
- 服务端组件:使用
-
清晰的职责分离:
createClient():通用客户端,自动适应环境createServerSideClient():专门用于服务器端操作
使用示例
在页面组件中使用:
// app/posts/[id]/page.tsx
import { createClient } from "@/lib/supabase/server"
export default async function PostPage({ params }) {
const supabase = await createClient()
// ...
}
在服务端操作中使用:
// app/actions/profile-actions.ts
'use server'
import { createServerSideClient } from '@/lib/supabase/server'
export async function updateProfile(userId, updates) {
const supabase = createServerSideClient()
// ...
}
这个问题的解决让我对 Next.js 的混合渲染模式有了更深的理解:
- Server Components 和 Client Components 有明确的边界
- 共享代码需要考虑运行环境的差异
- 条件渲染是解决这类问题的有效手段
Next.js unstable_cache 函数中,不能使用cookie
Route /[locale]/dashboard used
cookies()inside a function cached withunstable_cache(). Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function usecookies()outside of the cached function and pass the required dynamic data in as an argument.
- bug 本质
动态数据(cookies/headers)不能进缓存函数。 unstable_cache 是用来缓存异步函数执行的结果的。被缓存的函数必须是 “纯静态” 的,不能直接读动态数据源,
cookies()、headers()、searchParams,因为这些是每个请求 / 用户都不同的,一旦缓存就会串用户、出安全问题Next.js。