Go Back

NextJS next/dynamic import still somehow using require?

Posted: 

Ran into an odd issue when trying to dynamically import our custom component library using the NextJS dynamic function. Here is a simplified version of what I was trying to do.

const DynamicButton = dynamic(() =>
import("my-component-library").then((mod) => mod.Button)
);

Pretty much right out of the NextJS docs. Running npm run dev and everything seems to work fine.

Module not found? huh?!

The issue arises when you try to build. Running npm run build yields the following error.

Module not found: Package path . is not exported from package /Users/fakeuser/Sites/nextjs/node_modules/my-component-library
(see exports field in /Users/fakeuser/Sites/nextjs/node_modules/my-component-library/package.json)

Ok...that doesn't make any sense. Taking a look at that very package.json in the node_modules folder and I find this in the exports field:

"exports": {
".": {
    "import": "./dist/index.es.js",
"types": "./dist/index.d.ts"
}
}

Pretty much looks like it exports . to me. What is going on here?

Why are you looking for require?

Just for the sake of not knowing what else to try, I added the require condition to the exports field that is supposed to only be used with CommonJS. In this case I didn't have a CommonJS version of my module so I just slapped in the same ES module file.

"exports": {
".": {
"import": "./dist/index.es.js",
      "require": "./dist/index.es.js",
"types": "./dist/index.d.ts"
}
}

And what do you know, that worked!

Is next/dynamic secretly still using require under the hood?

But what does that mean? Does it mean that under the hood the dynamic function of NextJS is dynamically importing a module using CommonJS even when the entire project I'm working on is ES modules?

I looked through the code of that next/dynamic function and didn't see anything obvious. It's basically just using the import function that I pass it.

The only thing I could possible think of is that somehow in the webpack transformations it's turning my import function into something else.

Whatever the reason at this point, for now the fix was adding the require condition to the export map in package.json. Hopefully in the future as NextJS moves closer to all ESM we won't need to do this, as I'm just waiting for the weird bugs that are going to come out of this. But for now it's really all I can do save not using dynamic imports.

React.lazy with Suspense

Well I guess there is one thing. It did seem to work when I tried the native React.lazy and Suspense method to which dynamic is just a wrapper for anyway. I guess I could just do that. But that dynamic function is just so nice...

ChatGPT suggested titles

I just had to share this because I'm still playing with how I can use AI in my blog writing process. I first gave it this blog article and then asked it to give me a title that would really make people want to click on it. I couldn't quite pick one of these cause I just don't roll that way, but I thought the titles were entertaining nonetheless.

For your enjoyment:

  • "Unraveling the Mystery: NextJS Dynamic Imports, CommonJS Quirks, and the Fix That Saved My Build"
  • "NextJS Dynamic Imports Dilemma: Cracking the Code, CommonJS Conundrums, and the Genius Fix You Didn't See Coming!"
  • "🚀 NEXTJS SHOCKER! Dynamic Imports Gone Haywire? Uncover the Jaw-Dropping CommonJS Secret That Rescued My Build! 🔥"
  • "Unlocking the NextJS Enigma: Is Dynamic Import Secretly Clinging to 'require'? Demystifying the ES Module Puzzle!"