You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在getServerSideProps中获取NextAuth会话时出现fs模块未找到错误

解决NextAuth导入authOptions导致客户端fs模块错误的方案

你的问题核心是客户端代码间接引入了仅服务器端可用的依赖:由于authOptions包含EmailProvider,而EmailProvider依赖nodemailer,nodemailer又依赖Node.js的fs模块,客户端环境无法识别fs,因此编译报错。以下是几种可靠的解决思路:


方案一:拆分auth配置(推荐)

将authOptions拆分为共享配置和服务器端专属配置,避免客户端加载服务器端依赖:

  1. 创建共享配置文件(lib/auth-shared.ts):
// lib/auth-shared.ts
export const sharedAuthOptions = {
  session: {
    strategy: 'jwt', // 你的session策略
  },
  callbacks: {
    // 仅包含无服务器端依赖的回调,比如session、jwt处理
    session: ({ session, token }) => ({
      ...session,
      user: { ...session.user, id: token.sub },
    }),
  },
  // 其他不依赖服务器模块的配置项
};
  1. 在NextAuth入口文件中扩展配置:
// pages/api/auth/[...nextauth].ts
import NextAuth from 'next-auth';
import EmailProvider from 'next-auth/providers/email';
import { PrismaAdapter } from '@next-auth/prisma-adapter';
import prisma from '@/lib/prisma';
import { sharedAuthOptions } from '@/lib/auth-shared';

// 仅在服务器端加载的完整配置
export const authOptions = {
  ...sharedAuthOptions,
  adapter: PrismaAdapter(prisma),
  providers: [
    EmailProvider({
      server: process.env.EMAIL_SERVER,
      from: process.env.EMAIL_FROM,
    }),
  ],
};

export default NextAuth(authOptions);
  1. 在组件的getServerSideProps中动态导入完整配置:
// components/MyComponent.tsx
export const getServerSideProps = async ({ req, res }) => {
  // 仅在服务器端执行导入,客户端不会加载这些代码
  const { authOptions } = await import('../pages/api/auth/[...nextauth]');
  const serverSession = await getServerSession(req, res, authOptions);
  
  return {
    props: { serverSession },
  };
};

export default function MyComponent({ serverSession }) {
  return (
    <div>
      {serverSession ? `已登录:${serverSession.user.email}` : '未登录'}
    </div>
  );
}

方案二:优化动态导入逻辑

如果你不想拆分配置,确保仅在服务器端执行authOptions的导入,且组件不进行静态导入:

// components/MyComponent.tsx
// 注意:不要在组件顶部静态导入authOptions!

export const getServerSideProps = async ({ req, res }) => {
  // 使用await import动态加载,仅在服务器端运行
  const { authOptions } = await import('../pages/api/auth/[...nextauth]');
  const serverSession = await getServerSession(req, res, authOptions);
  
  return {
    props: { serverSession },
  };
};

export default function MyComponent({ serverSession }) {
  // 组件逻辑
}

这种方法的关键是移除组件顶部的静态导入,避免客户端打包时引入服务器端依赖。


方案三:调整Webpack配置(补充方案)

通过Webpack配置,在客户端环境中忽略或mock服务器端依赖:

// next.config.js
module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      // Mock Node.js核心模块(fs/net/tls)
      config.resolve.fallback = {
        ...config.resolve.fallback,
        fs: false,
        net: false,
        tls: false,
      };
      // 忽略nodemailer中依赖fs的dkim模块
      config.plugins.push(
        new config.webpack.IgnorePlugin({
          resourceRegExp: /nodemailer\/lib\/dkim/,
        })
      );
    }
    return config;
  },
};

这种方法可以临时解决报错,但可能会引入其他隐藏问题,建议结合前两种方法使用。


内容的提问来源于stack exchange,提问作者johngraham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 14:43:12