Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReferenceError: require is not defined #33741

Closed
jibrail-idris opened this issue Jun 5, 2020 · 29 comments · Fixed by #37852
Closed

ReferenceError: require is not defined #33741

jibrail-idris opened this issue Jun 5, 2020 · 29 comments · Fixed by #37852
Labels
errors Issues and PRs related to JavaScript errors originated in Node.js core. esm Issues and PRs related to the ECMAScript Modules implementation.

Comments

@jibrail-idris
Copy link

jibrail-idris commented Jun 5, 2020

What steps will reproduce the bug?

  1. Download LTS 12.18.0 from https://nodejs.org/dist/v12.18.0/node-v12.18.0-linux-x64.tar.xz
  2. Untar compressed file
  3. Save a js file with the following code: (Let's called it test.js)
    console.log(require)
  4. Run //node-v12.18.0-linux-x64/bin/node test.js
  5. Node returns error output stating that require is not defined.

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.

$ node
Welcome to Node.js v12.18.0.
Type ".help" for more information.
> console.log(require)
[Function: require] {
  resolve: [Function: resolve] { paths: [Function: paths] },
  main: undefined,
  extensions: [Object: null prototype] {
    '.js': [Function],
    '.json': [Function],
    '.node': [Function]
  },
  cache: [Object: null prototype] {}
}

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 defined

Additional information

The issue does not happen in older node versions. See text output below

$ node --version
v8.10.0
$ node test.js
{ [Function: require]
  resolve: { [Function: resolve] paths: [Function: paths] },
  main:
   Module {
     id: '.',
     exports: {},
     parent: null,
     filename: '/somedirectory/test.js',
     loaded: false,
     children: [],
     paths:
      [ '/somedirectory/node_modules',
      ...,
      ...,
        '/node_modules' ] },
  extensions: { '.js': [Function], '.json': [Function], '.node': [Function] },
  cache:
   { '/somedirectory/test.js':
      Module {
        id: '.',
        exports: {},
        parent: null,
        filename: '/somedirectory/test.js',
        loaded: false,
        children: [],
        paths: [Array] } } }
@richardlau
Copy link
Member

cc @nodejs/modules-active-members

@benjamingr
Copy link
Member

Hey thank you for the report and engaging, this is actually intentional. You cannot require from an ESM module - you need to use createRequire :]

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)

@jkrems
Copy link
Contributor

jkrems commented Jun 5, 2020

Can 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”.

@benjamingr
Copy link
Member

BTW: Apologies, I somehow missed that OP did not realize they were running inside module context 🙏 Thanks for the comment Jan.

@BridgeAR
Copy link
Member

BridgeAR commented Jun 5, 2020

Let's reopen for now.

@benjamingr benjamingr reopened this Jun 5, 2020
@jibrail-idris
Copy link
Author

@jkrems You are right. The module "type" was causing the issue. Thank you for flagging that out.

@GeoffreyBooth
Copy link
Member

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"”

@jibrail-idris
Copy link
Author

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"”

Yes. That will be very helpful!

@benjamingr
Copy link
Member

Let's reopen it the meantime for the error message improvement.

@benjamingr benjamingr reopened this Jun 6, 2020
@juanarbol
Copy link
Member

I could work on this

@baselsoftwaredev
Copy link

Thanks for this thread, was facing the same issue. More precise error message would definitely help people.

@ark334
Copy link

ark334 commented Oct 10, 2020

Hey thank you for the report and engaging, this is actually intentional. You cannot require from an ESM module - you need to use createRequire :]

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.

@priya-concetto
Copy link

ReferenceError: createRequire is not defined

@benjamingr
Copy link
Member

@priya-concetto did you import it from "module" ?

@targos targos added errors Issues and PRs related to JavaScript errors originated in Node.js core. esm Issues and PRs related to the ECMAScript Modules implementation. labels Dec 27, 2020
aduh95 added a commit to aduh95/node that referenced this issue Mar 21, 2021
aduh95 added a commit to aduh95/node that referenced this issue Mar 21, 2021
@aduh95 aduh95 closed this as completed in 7b2bad4 Apr 13, 2021
BethGriggs pushed a commit that referenced this issue Apr 15, 2021
targos pushed a commit that referenced this issue May 30, 2021
targos pushed a commit that referenced this issue Jun 5, 2021
targos pushed a commit that referenced this issue Jun 11, 2021
@reuben4310
Copy link

Hey thank you for the report and engaging, this is actually intentional. You cannot require from an ESM module - you need to use createRequire :]

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

@iva2k
Copy link

iva2k commented Jul 29, 2021

There's an interesting problem with node checking package.json for type: module when 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.

@ljharb
Copy link
Member

ljharb commented Jul 29, 2021

@iva2k either name the script .cjs, or better, remove type entirely and name your ESM files as .mjs.

@iva2k
Copy link

iva2k commented Jul 29, 2021

@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.

@ljharb
Copy link
Member

ljharb commented Jul 29, 2021

@iva2k that's another option (specifically, you'd need scripts/package.json to have "type": "commonjs"), but in a type:module package, you might as well use .cjs for your CJS files.

@iva2k
Copy link

iva2k commented Jul 29, 2021

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?

@iva2k
Copy link

iva2k commented Jul 29, 2021

I jumped to conclusion too early that stub package.json works. Now npm run build fails 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.js

Throwing 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.

@ljharb
Copy link
Member

ljharb commented Jul 29, 2021

type in a package.json only affects that package's boundary. If you have type module, a webpack config probably needs to be named .cjs also.

@iva2k
Copy link

iva2k commented Jul 29, 2021

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!

@ljharb
Copy link
Member

ljharb commented Jul 29, 2021

unfortunately type module causes nothing but problems ¯\_(ツ)_/¯

@iva2k
Copy link

iva2k commented Jul 29, 2021

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)

@aduh95
Copy link
Contributor

aduh95 commented Jul 29, 2021

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 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);

@reuben4310
Copy link

reuben4310 commented Jul 29, 2021 via email

@benjamingr
Copy link
Member

@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 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
errors Issues and PRs related to JavaScript errors originated in Node.js core. esm Issues and PRs related to the ECMAScript Modules implementation.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

16 participants