网站搜索

node.js - 在 getServerSideProps 内使用 EmailProvider 获取 NextAuth 会话时抛出 fs “模块未找到”


我正在尝试在 getServerSideProps 中从服务器端调用获取 NextAuth 会话,并且我正在使用带有 NextAuth 的 EmailProvider。我正在按照 NextAuth 文档中的示例,从 getServerSideProps 获取会话。

在 [...nextauth].ts] 配置文件中,我使用了 EmailProvider。

// pages/api/auth/[...nextauth].ts

import NextAuth from 'next-auth';
import EmailProvider from 'next-auth/providers/email';

export const authOptions = {
  adapter: PrismaAdapter(prisma),
  providers: [
    EmailProvider({ ... }),
  ],
};

export default NextAuth(authOptions);

在一个前端组件中,我尝试这样获取会话:

// components/MyComponent.tsx

import { authOptions } from '@auth/[...nextauth]';

export const getServerSideProps = async ({ req, res }) => {
  const serverSession = await getServerSession(req, res, authOptions);
  
  return {
    props: { serverSession },
  };
};

我甚至在 next.config.js 中添加了 webpack 配置,以在客户端时忽略仅服务器使用的代码:

// next.config.js
module.exports = {
  webpack: (config, { isServer, webpack }) => {
    if (!isServer) {
      config.plugins.push(
        new webpack.IgnorePlugin({ resourceRegExp: /^\/pages\/api\/auth\/$/ })
      );
    }
  }
}

问题是当我在前端组件文件中添加 import { authOptions } from '@auth/[...nextauth]'; 时,它会抛出编译错误:

// compilation error
error - ./node_modules/nodemailer/lib/dkim/index.js:10:0
Module not found: Can't resolve 'fs'

https://nextjs.org/docs/messages/module-not-found

Import trace for requested module:
./node_modules/nodemailer/lib/mailer/index.js
./node_modules/nodemailer/lib/nodemailer.js
./node_modules/next-auth/providers/email.js
./pages/api/auth/[...nextauth].ts
./components/MyComponent.tsx
./pages/index.tsx

我猜当我在 MyComponent 中导入 [...nextauth] 时,这是预期的行为,它会导入 EmailProvider,而 EmailProvider 又导入 nodemailer,nodemailer 又导入 fs。由于 MyComponent 在客户端运行,它会抛出错误,因为 fs 模块在客户端不可用。

所以我尝试了几件事情:

  • 在我的 package.json 中添加 "fs": false(源代码在这里)。这作为临时解决方案是可行的,但随后更多的模块需要被添加到 package.json 中,我就会陷入一个泥潭,最终导致无法使用 prisma。
  • 在 getServerSideProps 内导入 authOptions(示例)。这并没有影响错误。

还有其他想法吗?谢谢!

答案#1

啊,所以组件不能进行服务器端渲染(SSR),只有页面可以。这里有更多的文档。

所以为了解决这个问题,我将 getServerSideProps 移到了一个页面(例如 pages/index.tsx 或 pages/ 根目录下的任何其他页面)。代码看起来一样,下面复制了一份,但代码所在的文件不同。

// components/MyComponent.tsx <-- this is wrong
// ^^ IT SHOULD NOT BE A COMPONENT

// pages/index.tsx <-- or whatever page you're using
// ^^ IT SHOULD BE A PAGE INSTEAD OF A COMPONENT

import { authOptions } from '@auth/[...nextauth]';

export const getServerSideProps = async ({ req, res }) => {
  const serverSession = await getServerSession(req, res, authOptions);
  
  return {
    props: { serverSession },
  };
};