Next.js 14.0.3+next-auth+NestJS后端:开发正常构建失败
问题描述
基于Next.js 14.0.3开发应用,使用next-auth实现认证,外部NestJS后端处理授权与JWT验证。开发环境执行npm run dev时一切正常,但执行npm run build构建生产版本时遇到如下类型错误:
.next/types/app/api/auth/[...nextauth]/route.ts:8:13 Type error: Type 'OmitWithTag<typeof import("U:/sid/sid-front/app/api/auth/[...nextauth]/route"), "POST" | "GET" | "HEAD" | "OPTIONS" | "PUT" | "DELETE" | "PATCH" | "config" | "generateStaticParams" | "revalidate" | ... 5 more ... | "maxDuration", "">' does not satisfy the constraint '{ [x: string]: never; }'. Property 'authOptions' is incompatible with index signature. Type 'AuthOptions' is not assignable to type 'never'.
路由文件代码(app/api/auth/[...nextauth]/route.ts)
import { NextAuthOptions } from "next-auth"; import { JWT } from "next-auth/jwt"; import NextAuth from "next-auth/next"; import CredentialsProvider from "next-auth/providers/credentials"; async function refreshToken(token: JWT): Promise<JWT> { const res = await fetch(process.env.NEXT_PUBLIC_API_URL + "/auth/refresh", { method: "POST", headers: { authorization: `Refresh ${token.backendTokens.refreshToken}`, }, }); console.log("refreshed"); const response = await res.json(); return { ...token, backendTokens: response, }; } export const authOptions: NextAuthOptions = { providers: [ CredentialsProvider({ name: "Credentials", credentials: { email: { label: "Email", type: "text", placeholder: "jsmith", }, password: { label: "Password", type: "password" }, }, async authorize(credentials, req) { if (!credentials?.email || !credentials?.password) return null; const { email, password } = credentials; const res = await fetch( process.env.NEXT_PUBLIC_API_URL + "/auth/login", { method: "POST", body: JSON.stringify({ email, password, }), headers: { "Content-Type": "application/json", }, } ); if (res.status == 401) { console.log(res.statusText); return null; } const user = await res.json(); return user; }, }), ], callbacks: { async jwt({ token, user }) { if (user) return { ...token, ...user }; if (new Date().getTime() < token.backendTokens.expiresIn) return token; return await refreshToken(token); }, async session({ token, session }) { session.user = token.user; session.backendTokens = token.backendTokens; return session; }, }, }; const handler = NextAuth(authOptions); export { handler as GET, handler as POST };
类型声明文件代码(next-auth.d.ts)
import NextAuth from "next-auth"; declare module "next-auth" { interface Session { user: { id: number; email: string; name: string; }; backendTokens: { accessToken: string; refreshToken: string; expiresIn: number; }; } } import { JWT } from "next-auth/jwt"; declare module "next-auth/jwt" { interface JWT { user: { id: number; email: string; name: string; }; backendTokens: { accessToken: string; refreshToken: string; expiresIn: number; }; } }
原因分析与解决方法
原因
Next.js 14的App Router在生产构建阶段会严格校验API路由的导出内容:API路由文件只能导出HTTP方法处理函数(如GET、POST)以及Next.js允许的特殊配置项(如config),不能导出其他自定义变量。你当前代码中导出了authOptions,触发了类型检查的约束,导致构建失败。开发环境的类型检查规则相对宽松,所以没有暴露这个问题。
解决步骤
- 修改
app/api/auth/[...nextauth]/route.ts中的authOptions定义,去掉export关键字,将其改为局部变量:
// 去掉前面的export const authOptions: NextAuthOptions = { // 原配置内容不变 };
- 保存修改后,重新执行
npm run build即可通过类型检查。
这个修改不会影响next-auth的功能,因为authOptions只需要在当前路由文件内被NextAuth()函数使用,不需要对外暴露。
内容的提问来源于stack exchange,提问作者Nazar Duma
相关产品推荐
相关产品推荐

