Closed mikestopcontinues closed 2 years ago
not the op, but reproducible with this. both import
and import()
fail with:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /data/Development/playground/issue-next-esm/node_modules/p-queue/dist/index.js
require() of ES modules is not supported.
require() of /data/Development/playground/issue-next-esm/node_modules/p-queue/dist/index.js from /data/Development/playground/issue-next-esm/.next/server/pages/index.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename /data/Development/playground/issue-next-esm/node_modules/p-queue/dist/index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /data/Development/playground/issue-next-esm/node_modules/p-queue/package.json.
Thanks @stefanprobst I didn't see they'd requested a repro. :)
Some background: @sindresorhus is in the process of moving most of his packages to ESM only in 2021. This error will likely become more common as more packages move to ESM only.
I ran into the same issue with https://github.com/sindresorhus/slugify. Workaround: don't upgrade to latest major.
workaround: use next-transpile-modules
const withTM = require('next-transpile-modules')([
// ...
'p-debounce', // ESM module
])
I like @yurtaev's solution, but if anyone's relying on npm-check-updates
, my fix was to prefix breaking module versions with =
, then run ncu -u --rejectVersion '/^=/'
.
We have encountered the same issue with yjs
(version 13.5.5). For us, webpack was compiling the module version of yjs
, but was not compiling anything yjs
was importing, namely a package called lib0
. This resulted in an ESM (yjs) importing a CJS module (lib0). Low level, in case it helps anyone: the specific issue was that yjs
was adding suffixes to all imports (eg import { observable } from 'lib0/observable.js
) which was invalidating conditional exports, resulting to the ESM => CJS import mentioned above.
The solution for us was to add the following line to next.config.js:
module.exports = {
webpack: function (config, options) {
config.externals = [...config.externals, 'yjs'];
return config;
},
};
This makes webpack treat yjs
as an external dependency (non-transpiled that is), and everything goes through the proper builds.
UPDATE: no, this only made the build work. I saw a require('yjs');
in the server build artifacts, but it does not work on the client.
Same issue with new version of d3 modules like d3-scale
A more permanent solution would be to import()
everything instead of require()
ing it. This is possible since next no longer supports node 10 in canary
. https://github.com/vercel/next.js/blob/f18ce55d8ac85f8abaa51bcd8a663ef5c8e78d28/package.json#L140-L142
This still has the "please add a complete reproduction" tag, so I'm linking a minimal repo:
https://github.com/JohnForster/esm-minimal-repo
This example also does not work with withTM, so if anyone can give advice on how to get it running, I'd appreciate it.
For anyone running into similar problems ( @mario-jerkovic ?) that aren't immediately fixed with next-transpile-modules, you may need to include sub-dependencies in your next.config.js as well. I just ran into this problem with d3-delaunay but it might be present in other d3 modules as well.
Keep an eye on the error messages to see which modules you need to add.
My config looks like:
// next.config.js
const withTM = require("next-transpile-modules")([
"d3-delaunay", // The package I'm trying to import
"delaunator", // A dependency of d3-delaunay
"robust-predicates", // A dependency of delaunator
]);
module.exports = withTM({
reactStrictMode: true,
});
Could the tag please add a complete reproduction
please be removed, as this issue has a reproduction?
This is being worked on by @sokra currently, you can check out the initial PR here: https://github.com/vercel/next.js/pull/27069. Do keep in mind this is still work in progress.
You can try the latest canary version and verify if it does work in your cases.
@sokra I don't know if this is a bug or not, but when a pure ESM library imports a library that has "module" (non-standard ESM field) and "main" but not "exports", it fails. Is it planned to support non-standard fields? Or "exports" only? There is a large set of such libraries with "main" / "module" fields, so that's why I'm asking
Do you have a name of such a package for reference?
@sokra sure, here are some ("module" / "main" but no "exports"):
not sure if I got this right, but it doesn't seem to work on next@11.0.2-canary.16
when a mixed package uses another mixed package. It results in this error:
import { etherJsFetcher } from 'ether-swr';
^^^^^^^^^^^^^^
SyntaxError: Named export 'etherJsFetcher' not found. The requested module 'ether-swr' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from 'ether-swr';
const { etherJsFetcher } = pkg;
Both have "exports" with "require" / "import" though. Although, ether-swr
here doesn't have a "type": "module" field, but AFAIK it should work anyway bc of "exports.import" field.
To reproduce:
create-next-app --example hello-world hello-world-app
npm install next-eth ethers
module.exports = {
experimental: {
esmExternals: 'loose'
}
}
Here are package.jsons of both packages for reference:
Weirdly enough, direct import of a mixed package works. But using a package that imports a mixed package doesn't
@talentlessguy you can try if your package is a correct ESM by typing node -e 'import("ether-swr")'
, which leads to:
(node:31920) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
C:\Repos\_\next-23725\node_modules\ether-swr\esm\index.js:1
export * from './ether-js-fetcher';
^^^^^^
SyntaxError: Unexpected token 'export'
Although,
ether-swr
here doesn't have a "type": "module" field, but AFAIK it should work anyway bc of "exports.import" field.
Yep, that's exactly the problem. The package is missing "type": "module"
(or the .mjs extensions). The exports
field has no influence on the decision if ESM or CJS. Best put a package.json with only {"type": "module"}
into your ./esm
directory -> ./esm/package.json
. That would make all files in that directory ESM.
If anyone gets here because of the new unified
stack, maybe this will save you some time:
const withTM = require("next-transpile-modules")([
"bail",
"comma-separated-tokens",
"hast-to-hyperscript",
"hast-util-from-parse5",
"hast-util-has-property",
"hast-util-heading-rank",
"hast-util-parse-selector",
"hast-util-raw",
"hast-util-sanitize",
"hast-util-to-parse5",
"hast-util-to-string",
"hastscript",
"html-void-elements",
"is-plain-obj",
"mdast-util-from-markdown",
"micromark-core-commonmark",
"micromark-factory-destination",
"micromark-factory-label",
"micromark-factory-space",
"micromark-factory-title",
"micromark-factory-whitespace",
"micromark-util-combine-extensions",
"micromark-util-character",
"micromark-util-chunked",
"micromark-util-classify-character",
"micromark-util-decode-numeric-character-reference",
"micromark-util-html-tag-name",
"micromark-util-normalize-identifier",
"micromark-util-resolve-all",
"micromark-util-subtokenize",
"micromark-util-symbol",
"property-information",
"rehype-autolink-headings",
"rehype-raw",
"rehype-react",
"rehype-sanitize",
"rehype-slug",
"remark-parse",
"space-separated-tokens",
"trough",
"unified",
"unist-util-stringify-position",
"vfile",
"web-namespaces"
]);
@frattaro you could also try with setting:
// next.config.js
const config = {
experimental: {
esmExternals: true,
},
}
module.exports = config
(requires next@canary
version)
@stefanprobst Doesn't appear to make a difference -- want me to set up a repro repo?
it has been working for me with xdm
and retext
:shrug:
@frattaro can you make sure you're on next@canary
?
Definitely am
Can you provide a reproduction? Then we can have a look into it 👍
Creating the repro revealed my issue. Alone, using esmExternals
with the unified
stack works just fine.
I have another package that uses import
s, does not have type: "module"
in it's package.json and needs next-transpile-modules
. Unfortunately, it seems you can't use esmExternals
alongside next-transpile-modules
. So I added type: "module"
directly to the package.json
of the package in question, and then found another issue with it. It has a babel preset that uses require
in it. I renamed the babel preset's suffix to .cjs
, and that worked. But then I ran into:
error - ./node_modules/@my-package/path/app.scss
Global CSS cannot be imported from within node_modules.
And at that point I stopped trying to fix it :)
Edit: the package I'm importing is a UI framework, so it's going to have some edge cases
another version of @frattaro
I'm using rehype-raw
, rehype-slug
, remark-gfm
const withTM = require("next-transpile-modules")([
"bail",
"ccount",
"comma-separated-tokens",
"hast-to-hyperscript",
"hast-util-from-parse5",
"hast-util-has-property",
"hast-util-heading-rank",
"hast-util-parse-selector",
"hast-util-raw",
"hast-util-to-parse5",
"hast-util-to-string",
"hastscript",
"html-void-elements",
"is-plain-obj",
"markdown-table",
"mdast-util-find-and-replace",
"mdast-util-from-markdown",
"mdast-util-gfm",
"mdast-util-to-markdown",
"micromark-extension-gfm",
"micromark-factory-space",
"micromark-util-combine-extensions",
"micromark-util-character",
"micromark-util-chunked",
"micromark-util-classify-character",
"micromark-util-encode",
"micromark-util-resolve-all",
"micromark-util-sanitize-uri",
"micromark-util-symbol",
"property-information",
"rehype-raw",
"rehype-slug",
"remark-gfm",
"remark-parse",
"space-separated-tokens",
"trough",
"unified",
"unist-util-stringify-position",
"vfile-location",
"web-namespaces",
]);
@exneval I'm trying to use it with unist-util-visit
& I used next-transpile-modules
like you said but still getting an error:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: my-app\node_modules\unist-util-visit\index.js
require() of ES modules is not supported.
require() of my-app\node_modules\unist-util-visit\index.js from my-app\rehype\highlight-code.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from my-app\node_modules\unist-util-visit\package.json.
at new NodeError (node:internal/errors:363:5)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1126:13)
at Module.load (node:internal/modules/cjs/loader:989:32)
at Function.Module._load (node:internal/modules/cjs/loader:829:14)
at Module.require (node:internal/modules/cjs/loader:1013:19)
at require (node:internal/modules/cjs/helpers:93:18)
at Object.<anonymous> (my-app\rehype\highlight-code.js:4:15)
at Module._compile (node:internal/modules/cjs/loader:1109:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1138:10)
at Module.load (node:internal/modules/cjs/loader:989:32) {
code: 'ERR_REQUIRE_ESM'
const withTranspileModules = require('next-transpile-modules')([
'hast-util-to-html',
'hast-util-to-string',
'rehype-slug',
'remark-gfm',
'remark-parse',
'unified',
'unist-util-visit',
])
const withBundleAnalyzer = bundleAnalyzer({
enabled: process.env.ANALYZE === 'true',
})
module.exports = withTranspileModules(withBundleAnalyzer(nextConfig))
I even tried changing my custom ./rehype/highlight-code.js
to use import
instead of require
but it gave:
SyntaxError: Cannot use import statement outside a module
Do I need to do anything else?
@deadcoder0904 maybe setup issue? I'm using next compose plugins to wrap the transpile,
This config, for latest rehype-raw
, rehype-slug
and remark-gfm v1.0.0
const withPlugins = require("next-compose-plugins");
const withTM = require("next-transpile-modules")([
"escape-string-regexp",
"comma-separated-tokens",
"hast-to-hyperscript",
"hast-util-from-parse5",
"hast-util-has-property",
"hast-util-heading-rank",
"hast-util-parse-selector",
"hast-util-raw",
"hast-util-to-parse5",
"hast-util-to-string",
"hastscript",
"html-void-elements",
"property-information",
"rehype-raw",
"rehype-slug",
"space-separated-tokens",
"vfile-location",
"web-namespaces",
]);
const nextConfig = {
eslint: {
ignoreDuringBuilds: true,
},
};
module.exports = withPlugins([withTM], nextConfig);
or maybe you can try NextJS 11.1.0 , and try
// next.config.js
module.exports = {
// Prefer loading of ES Modules over CommonJS
experimental: { esmExternals: true }
}
no need to use transpile anymore, finally NextJS support it, and it become default in NextJS 12
@exneval I thought I needed to use even next-transpile-modules
to make ESM modules work with Next.js v11.1.0. If it's not the case, then I'm wondering why it isn't working?
You also don't need to use next-compose-plugins
as it would work properly even without it if you wrap it. I'll probably open an issue on unist-util-visit
.
@deadcoder0904 can you provide a reproduction repository so that we can have a look?
@timneutkens take a look here -> https://github.com/deadcoder0904/next-esm-error
Install & run to see errors :)
@deadcoder0904
looks like you didn't actually enable the esmExternals
config?
@stefanprobst I did actually, just not in the repro. Pushed a new commit but still error :)
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /../next-esm-error/node_modules/hast-util-to-string/index.js require() of ES modules is not supported. require() of /../next-esm-error/node_modules/hast-util-to-string/index.js from /../next-esm-error/rehype/highlight-code.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules. Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /../next-esm-error/node_modules/hast-util-to-string/package.json.
@deadcoder0904 Your problem is unrelated to next.js/webpack processing your files.
You are trying to require()
an ESM, which is not allowed (which is also want the node.js error is trying to tell you). You need to use import
or import()
to import an ESM.
This happens while loading the next.config.js.
Sadly next.js require()
s the config file, so you can't really use import
there. I guess that need to be changed in next.js
@sokra but I can't import
ESM modules from the folder rehype/
as it gives another error:
SyntaxError: Cannot use import statement outside a module
I already said this above :)
Sadly next.js require()s the config file, so you can't really use import there. I guess that need to be changed in next.js
Got it. So I cannot use ESM till next.config.js
can use import()
? Till then, is there any issue I should subscribe to?
Edit: 13 hours later, came back to the same issue & looks like this is the issue I should be subscribed to :)
Failed to require remark-math.
I have to import remark-math in next.config.js . It gives this error when trying to import. I am on next@canary.
Error: failed to load next.config.js, see more info here https://nextjs.org/docs/messages/next-config-error
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/abc/Desktop/portfolio/node_modules/remark-math/index.js from /Users/abc/Desktop/portfolio/next.config.js not supported.
Instead change the require of index.js in /Users/abc/Desktop/portfolio/next.config.js to a dynamic import() which is available in all CommonJS modules.
at Object.
I'm guessing the use-case for importing remark
and rehype
plugins in next.config.js
is about configuring a markdown or MDX loader for webpack?
The whole unifiedjs
ecosystem has moved to ESM but all those plugins also have previous versions that were commonjs format, you can probably make this work if you roll them back to their previous major releases
Yes, that is what I am thinking of doing.
experimental: { esmExternals: true, },
This worked perfectly for me. Using "next": "11.1.3-canary.7"
and "unified": "10.1.0"
esmExternals: true
is now the default on next@canary
meaning it is going to be the default in the upcoming stable release. I'm going to close this issue as this particular case has been fixed. For loading ESModules in next.config.js
please subscribe to https://github.com/vercel/next.js/issues/9607.
@Prakhar-FF13 by any chance, did you manage to setup math display in MDX?
No I used mdx bundler by Kent c Dodds.
This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.
What version of Next.js are you using?
10.1.3
What version of Node.js are you using?
14.x
What browser are you using?
Chrome
What operating system are you using?
macOS
How are you deploying your application?
Vercel
Describe the Bug
p-queue
recently updated to using ESM modules, and it looks like some webpack configuration is required to support it. I doubt this is the last time this particular issue will come up.Expected Behavior
Users should be able to require ESM modules without getting an error.
To Reproduce
Install
p-queue@7.0.0
, import it, and try to start next.Thanks!