Repository navigation
ReferenceError: require is not defined #33741
Description
Activity
cc @nodejs/modules-active-members
Hey thank you for the report and engaging, this is actually intentional. You cannot
requirefrom an ESM module - you need to usecreateRequire:]import { createRequire } from 'module'; const require = createRequire(import.meta.url); // can now use `require` in an ESM
See this section in the docs regarding why and how to work around it.
(I'm closing since I don't think this is a bug - as usual, if anyone feels strongly feel free to reopen)
Reacted by Arcadio Ramírez, David Vernon, Praxis | Darian, Ricardo A. Martínez, KhalO, Emad AlOmari, pr0grara, Phanthakan Kiatpaisansophon, weisk, Ramazan ERTAN and 20 moreReacted by Priya Patel, Eduardo Larios, Nikita Fuchs, Roshi _ _, Anthony Comito, kt999, Krystian Kałwik, yusufnadar and William LahtiReacted by Roberto MachorroReacted by Farrukh, kevin olson, Homsi, Roberto Machorro and Nader NasrReacted by BenhiritosZikos96, lethal10010, Roberto Machorro and BibbyCan you verify that this happens in any directory? By default a .js file shouldn’t be treated as a module. I suspect that you may be in a directory (or nested directory below) where a package.json has a “type” field set to “module”.
Reacted by Benjamin Gruenbaum, Samuel, William Maia, Ben Biddington, Vinay Khade, shamilasallay, Mickey, Dawn James and Elijah RyersonReacted by SamuelReacted by SamuelReacted by SamuelBTW: Apologies, I somehow missed that OP did not realize they were running inside module context 🙏 Thanks for the comment Jan.
Reacted by zaqLet's reopen for now.
@jkrems You are right. The module "type" was causing the issue. Thank you for flagging that out.
We could perhaps expand the error message to include something like “file.js is loaded as an ES module due to /path/to/package.json containing "type": "module"”
Reacted by Jan Olaf Martin, Jibrail Idris, Benjamin Gruenbaum, T. Nishino, Hussam Dawood, Zach Thacker, Tiffany Warner, YuYang, Laure Ladastra, Felipe Grijó and 13 moreWe could perhaps expand the error message to include something like “file.js is loaded as an ES module due to /path/to/package.json containing "type": "module"”
Yes. That will be very helpful!
Reacted by Benjamin Gruenbaum, Hussam Dawood, Eduardo Larios, shalvishahgithub and SamuelLet's reopen it the meantime for the error message improvement.
I could work on this
Reacted by Benjamin Gruenbaum, Geoffrey Booth, Hussam Dawood, Jason Han, Kiryl Volkau and BaselReacted by amine djennadiThanks for this thread, was facing the same issue. More precise error message would definitely help people.
Reacted by Benjamin Gruenbaum, Arcadio Ramírez, 菱沼 雄太 and Tor Larsen13 remaining items
- added a commit that references this issue
on Jun 11, 2021 Hey thank you for the report and engaging, this is actually intentional. You cannot
requirefrom an ESM module - you need to usecreateRequire:]import { createRequire } from 'module'; const require = createRequire(import.meta.url); // can now use `require` in an ESM
See this section in the docs regarding why and how to work around it.
(I'm closing since I don't think this is a bug - as usual, if anyone feels strongly feel free to reopen)Thanks so much, I was having this issue using a type:module in package.json but now it's working thanks to your solution.
Not working for me
There's an interesting problem with node checking package.json for
type: modulewhen a package is built with a help of a script which is run by node, e.g.:package.json ... "type": "module", "scripts": { "build": "npm run increment && ...", "increment": "node scripts/increment_version.js", ...
Then node throws the error "ReferenceError: require is not defined" inside the scripts/increment_version.js. Removing
"type": "module",line removes the error, however, the resulting package is not correct as it needs"type": "module",in package.json.Is there a work-around for that? If not, then please reopen this issue to fix for the normal use of js scripts in package build time.
@iva2k either name the script
.cjs, or better, removetypeentirely and name your ESM files as.mjs.@ljharb - not my package, it is existing github repo I cloned and plan PR to add a feature. Changing whole build setup (which involves CI and CD) and renaming all files in the package is very steep price to pay. Is there a better fix, e.g. I'm pondering to add package.json file without "type: module" to scripts/ dir.
@iva2k that's another option (specifically, you'd need
scripts/package.jsonto have"type": "commonjs"), but in a type:module package, you might as well use.cjsfor your CJS files.It turns out an empty {} package.json in scripts/ solved that particular problem. I added "type: common" to be more specific, and that is clean enough workaround for this situation, works too.
Anyhow, it seems too far-fetched conclusion that node makes based on package.json contents. What is its rationale?
I jumped to conclusion too early that stub package.json works. Now
npm run buildfails in another .js file, now it is failing in node_modules, log snippet:> webpack -p --env.production ./node_modules/webpack-cli/bin/cli.js:93 throw err; ^ Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: ./webpack.config.jsThrowing package.json files around node_modules tree is not an easy workaround.
Also chasing few hundred package maintainers trying to convince them to rename all their .js files sounds like a terrible idea.typein a package.json only affects that package's boundary. If you have type module, a webpack config probably needs to be named.cjsalso.webpack-cli does not seem to find .cjs config file.
So the summary:
In a "type: module" package should not even try calling any of commonly used cli devDependencies, like webpack-cli - they will all break because node now infers that all .js executed are type: module based on project's package.json.
what a pickle!unfortunately type module causes nothing but problems ¯\_(ツ)_/¯
so module npm packages are a bad idea
what is the node's changelog that brought this change?
(this problematic project's travis.yml has "node_js: - '11'", and I have global node v12.20.0)The rationale was to allow users to write ES modules using
.jsas file extension. In the browser, we can use<script type="module">to tell the JS engine to parse the file as an ES module rather than a script, it was decided that usingpackage.jsonwould be the Node.js equivalent of that.For your particular issue, here's the solutions that could work:
- Remove
"type": "module"from thepackage.jsonand use the.mjsextension for all ES modules as @ljharb suggested. - Rename the Webpack config to
webpack.config.cjsand create awebpack.config.jsthat simply containsexport { default } from './webpack.config.cjs'; - Convert your
webpack.config.jsto an ES module by hand. You might be able to do that by replacingmodule.exportswithexport defaultand adding this snippet at the top of the file:import { createRequire } from 'module'; import { fileURLToPath } from 'url'; import { dirname } from 'path'; const require = createRequire(import.meta.url); const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename);
- Remove
- who's is sending me all this?…On Thu, Jul 29, 2021 at 6:04 AM Antoine du Hamel ***@***.***> wrote: The rationale was to allow users to write ES modules using .js as file extension. In the browser, we can use <script type="module"> to tell the JS engine to parse the file as an ES module rather than a script, it was decided that using package.json would be the Node.js equivalent of that. For your particular issue, here's the solutions that could work: - Remove "type": "module" from the package.json and use the .mjs extension for all ES modules as @ljharb <https://github.com/ljharb> suggested. - Rename the Webpack config to webpack.config.cjs and create a webpack.config.js that simply contains export { default } from './webpack.config.cjs'; - Convert your webpack.config.js to an ES module by hand. You might be able to do that by replacing module.exports with export default and adding this snippet at the top of the file: import { createRequire } from 'module';import { fileURLToPath } from 'url';import { dirname } from 'path';const require = createRequire(import.meta.url);const __filename = fileURLToPath(import.meta.url);const __dirname = dirname(__filename); — You are receiving this because you commented. Reply to this email directly, view it on GitHub <#33741 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AHSW5OVIAYO43HQCP7SUFRDT2ERRBANCNFSM4NTO7NIQ> .
@reuben4310 you are getting the emails because you commented on this post here: #33741 (comment)
@ArashAmini345 please open a new issue in the help repo https://github.com/nodejs/help/issues :)
What steps will reproduce the bug?
console.log(require)How often does it reproduce? Is there a required condition?
All the time.
What is the expected behavior?
The behavior should be similar to node executing the same one liner in REFL interactive shell.
What do you see instead?
$ node test.js
(node:13608) ExperimentalWarning: The ESM module loader is experimental. file:///somedirectory/test.js:1 console.log(require); ^ ReferenceError: require is not definedAdditional information
The issue does not happen in older node versions. See text output below