Bcrypt gives an Unexpected Token error with Next.js 14 (Client component) and Next-Auth

245 Views Asked by At

I have run into this issue where bcrypt does not work with Nextjs and gives this error:

 Module parse failed: Unexpected token (1:0) 

And in the console, I am getting this error:

./node_modules/@mapbox/node-pre-gyp/lib/util/nw-pre-gyp/index.html
Module parse failed: Unexpected token (1:0)

Basically I have a client component for infinite scrolling and in that client component, I am rendering a server component.

Now, that Server component checks for the logged in user. So Next-Auth and bcrypt gets involved. But because the Server component is rendered inside a client component, i am getting this error.

    {posts?.map((post) => {
 return (
 <PostListItem key={question?.id} postData={post} />

In the server component, I have this:

const PostListItem: React.FC<PostListItemProps> = async ({
 postData,
}) => {
 const currentUser = await getCurrentUser();

And here's what the getCurrentUser looks like:

import { getServerSession } from "next-auth/next";
import { options } from "@/app/api/auth/[...nextauth]/options";
import prismadb from "../prismadb";

export async function getSession() {
 return await getServerSession(options);
}

export async function getCurrentUser() {
 try {
 const session = await getSession();

 if (!session?.user?.email) {
 return null;
    }

 const currentUser = await prismadb.user.findUnique({
 where: {
 email: session.user.email as string,
      },

I have searched everywhere for a solution. On the Next.js github users have suggested to use 'bcryptjs' instead of 'bcrypt'. I tried that but it also throws a different error.

Some users have also suggested to change the next.config.js like so:

config.externals = [...config.externals, "bcrypt"];

But it also doesn't work.

What can i do to fix this situation?

2

There are 2 best solutions below

0
Lucas016 On

Bcrypt unfortunately will never be compatible with Next 14, more particularly on SSR systems or server components, as it uses Crypto behind the scenes, which in turn is also incompatible with server components. What works natively with node is now the Web Crypto API, perhaps if Bcrypt migrated to this new API, it would work.

In turn, bcrypt.js follows the same path, even if it works for an hour, it will stop at any time, in addition to being 30% slower than bcrypt.

0
Umair On

Finally got around the issue. Here how you can fix this:

First, in next.config.js

push bcrypt to config.externals like so:

  webpack: (config) => {
    config.externals = [...config.externals, "bcrypt"];
    return config;
  },

Then where ever you are using bcrypt,

instead of importing it in the traditional way (import bcrypt from 'bcrypt')

You need to import it like so:

const bcrypt = require("bcrypt");

And make sure to put it above the line where it's being used. For example,

const bcrypt = require("bcrypt");

const hashedPassword = await bcrypt.hash(password, 12);