I'm trying to get the NextAuth session from a server-side call in getServerSideProps
, and I'm using an EmailProvider
with NextAuth. I'm following an example from NextAuth's documentation to get the session from getServerSideProps
.
In the [...nextauth].ts]
configuration file, I use the 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);
In a frontend component, I attempt to get the session like this:
// components/MyComponent.tsx
import { authOptions } from '@auth/[...nextauth]';
export const getServerSideProps = async ({ req, res }) => {
const serverSession = await getServerSession(req, res, authOptions);
return {
props: { serverSession },
};
};
I even added webpack configs in next.config.js
to ignore server-only code when on the client:
// next.config.js
module.exports = {
webpack: (config, { isServer, webpack }) => {
if (!isServer) {
config.plugins.push(
new webpack.IgnorePlugin({ resourceRegExp: /^\/pages\/api\/auth\/$/ })
);
}
}
}
The problem is that when I add import { authOptions } from '@auth/[...nextauth]';
to my frontend component file, it throws a compilation error:
// 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
I guess this is expected behavior when I import [...nextauth]
in MyComponent
, it imports EmailProvider
, which imports nodemailer
, and nodemailer
imports fs
. Since MyComponent
runs on the client, it throws an error, because fs
module is not available on the client.
So I've tried a few things:
"fs": false
to my package.json
(source here) This works as a bandaid solution, but then more modules need to get added to package.json
, and I go down a rabbit hole that eventually prevents prisma
from being used.authOptions
inside getServerSideProps
(example). This did not affect the error.Any other ideas? Thank you!
Ah so components can't do server-side rendering (SSR), only pages can. Here's more documentation.
So to fix this, I moved getServerSideProps
to a page (e.g. pages/index.tsx
or any other page in the root of pages/
). The code looks the same, which is copied below, but the file that the code lives in is different.
// 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 },
};
};