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

"require is not defined in ES module scope" and mixed require/import using ESM with native modules #791

Open
dmfay opened this issue Oct 11, 2021 · 14 comments
Labels
bug Something isn't working

Comments

@dmfay
Copy link

dmfay commented Oct 11, 2021

I'm trying to compile an ES module ("type": "module") that uses tree-sitter. The compiled distributable winds up importing createRequire as expected, but still tries to load native code via old-fashioned require.

package.json
{
  "name": "ncctest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "tree-sitter": "^0.19.0",
    "tree-sitter-javascript": "^0.19.0"
  },
  "devDependencies": {
    "@vercel/ncc": "^0.31.1"
  }
}
index.js
'use strict';

import * as TreeSitter from 'tree-sitter';
import JavaScript from 'tree-sitter-javascript';

const parser = TreeSitter.default();

parser.setLanguage(JavaScript);
> npx ncc build index.js
> node dist/index.js
file:///home/dian/work/ncctest/dist/index.js:802
module.exports = require(__nccwpck_require__.ab + "build/Release/tree_sitter_runtime_binding.node")
^

ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and '/home/dian/work/ncctest/dist/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
    at Object.460 (file:///home/dian/work/ncctest/dist/index.js:802:1)
    at __nccwpck_require__ (file:///home/dian/work/ncctest/dist/index.js:860:41)
    at Object.525 (file:///home/dian/work/ncctest/dist/index.js:35:13)
    at __nccwpck_require__ (file:///home/dian/work/ncctest/dist/index.js:860:41)
    at file:///home/dian/work/ncctest/dist/index.js:880:69
    at file:///home/dian/work/ncctest/dist/index.js:891:3
    at ModuleJob.run (node:internal/modules/esm/module_job:183:25)
    at async Loader.import (node:internal/modules/esm/loader:178:24)
    at async Object.loadESM (node:internal/process/esm_loader:68:5)
    at async handleMainPromise (node:internal/modules/run_main:63:12)

The offending require in question:

/***/ 460:
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {

module.exports = require(__nccwpck_require__.ab + "build/Release/tree_sitter_runtime_binding.node")

/***/ }),
@unicornware
Copy link

unicornware commented Oct 13, 2021

having the same issue when trying to bundle a .mjs file (e.g: esm/index.mjs):

ReferenceError: require is not defined in ES module scope, you can use import instead
    at eval (eval at 874 (file:///Users/lex/Projects/FLDV/FLDV-P008/node_modules/@flex-development/trext/src/index.ts:7:15), <anonymous>:1:1)
    at Object.874 (file:///Users/lex/Projects/FLDV/FLDV-P008/node_modules/@flex-development/trext/src/index.ts:7:15)
    at __nccwpck_require__ (file:///Users/lex/Projects/FLDV/FLDV-P008/node_modules/@flex-development/trext/esm/trext.mjs:57:41)
    at file:///Users/lex/Projects/FLDV/FLDV-P008/node_modules/@flex-development/trext/esm/trext.mjs:100:81
    at file:///Users/lex/Projects/FLDV/FLDV-P008/node_modules/@flex-development/trext/esm/trext.mjs:113:3
    at ModuleJob.run (node:internal/modules/esm/module_job:175:25)
    at async Loader.import (node:internal/modules/esm/loader:178:24)
    at async Object.loadESM (node:internal/process/esm_loader:68:5)
/******/ 	// Execute the module function
/******/ 	var threw = true;
/******/ 	try {
/******/ 		__webpack_modules__[moduleId](module, module.exports, __nccwpck_require__);
/******/ 		threw = false;
/******/ 	} finally {
/******/ 		if(threw) delete __webpack_module_cache__[moduleId];
/******/ 	}

in my case, createRequire is only imported if i bundle src/index.ts instead (haven't tested it yet, but judging from the output i believe it works as expected).

unicornware added a commit to flex-development/trext that referenced this issue Oct 13, 2021
unicornware added a commit to flex-development/trext that referenced this issue Oct 13, 2021
@styfle styfle added the bug Something isn't working label Oct 14, 2021
@calvinf
Copy link

calvinf commented Dec 6, 2021

For my use case, I was using the sqlite and sqlite3 modules. I was able to avoid this error by leaving them external in my build command:

ncc build src/index.ts -m -s --target es2020 -e sqlite3 -e sqlite

I've got minify and source maps turned on. The relevant part for other folks should be the -e external flag.

@ariran5
Copy link

ariran5 commented Jan 6, 2022

same issue

@chrisreddington
Copy link

+1 - I believe I'm encountering this same issue - chrisreddington/rss-parser#120

@dmitrydutin
Copy link

dmitrydutin commented Mar 14, 2023

I have a similar problem

It seems that not all require() statements are replaced by __WEBPACK_EXTERNAL_createRequire(import.meta.url)("package_name");.

Fix

  • you can run ncc build without -m option;
  • replace all require("package_name") operators with __WEBPACK_EXTERNAL_createRequire(import.meta.url)("package_name");;
  • in dist directory run ncc build index.js -o ./ -m to create a minified version.

Example

// Before replacement
module.exports = eval("require")("@aws-sdk/signature-v4-crt");
module.exports = require("assert");
module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("http2");

// After replacement
module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("@aws-sdk/signature-v4-crt");
module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("assert");
module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("http2");

// After minification
e=>{e.exports=(0,o.createRequire)(import.meta.url)("@aws-sdk/signature-v4-crt")};
e=>{e.exports=(0,o.createRequire)(import.meta.url)("assert")};
e=>{e.exports=(0,o.createRequire)(import.meta.url)("http2")};

Comment:
It looks like some require("package_name") are being replaced with eval("require")("package_name"). Perhaps this should also be replaced with __WEBPACK_EXTERNAL_createRequire(import.meta.url)("package_name");.

It looks like a very bad trick, but it works for me. You can try to automate this.

My package.json

{
  "main": "build/index.js",
  "type": "module",
  "scripts": {
    "start": "ts-node src/index.ts",
    "build": "ncc build src/index.ts -o build -m --license licenses.txt"
  },
  "dependencies": {
    "@actions/core": "1.10.0",
    "@aws-sdk/client-s3": "3.289.0",
    "mime-types": "2.1.35"
  },
  "devDependencies": {
    "@types/mime-types": "2.1.1",
    "@types/node": "18.15.0",
    "@vercel/ncc": "0.36.1",
    "ts-node": "10.9.1",
    "typescript": "4.9.5"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "rootDir": "src",
    "outDir": "build",
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "lib": ["ESNext"],
    "types": ["node"],
    "strict": true,
    "noImplicitAny": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true
  },
  "exclude": [
    "build",
    "node_modules"
  ],
  "ts-node": {
    "esm": true
  }
}

@extravio
Copy link

Same error when using ES6 in a GitHub action based on https://github.com/actions/javascript-action
@vercel/ncc version 0.36.1

ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and '/runner/_work/_actions/[...]/dist/status-check/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
    at eval (eval at 553 (file:///runner/_work/_actions/[...]/dist/webpack:/javascript-action/node_modules/@vercel/ncc/dist/ncc/@@notfound.js:1:1), <anonymous>:1:1)
    at Object.553 (file:///runner/_work/_actions/[...]/dist/webpack:/javascript-action/node_modules/@vercel/ncc/dist/ncc/@@notfound.js:1:1)
    at __nccwpck_require__ (file:///runner/_work/_actions/[...]/dist/webpack:/javascript-action/webpack/bootstrap:21:1)
    at file:///runner/_work/_actions/[...]/dist/status-check/index.js:2827:78
    at file:///runner/_work/_actions/[...]/dist/status-check/index.js:2859:3
    at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
    at async Promise.all (index 0)
    at ESMLoader.import (node:internal/modules/esm/loader:530:24)
    at loadESM (node:internal/process/esm_loader:91:5)
    at handleMainPromise (node:internal/modules/run_main:65:12)

Any solution?

@DheerajYarlagadda
Copy link

DheerajYarlagadda commented Aug 3, 2023

npm install ncc@latest
npx ncc build ./path/file2build.js -o .
This has solved the issue for me.

@extravio
Copy link

extravio commented Aug 6, 2023

npm install ncc@latest npx ncc build ./path/file2build.js -o . This has solved the issue for me.

I guess you mean:

npm install @vercel/ncc@latest

I'm using "@vercel/ncc@lastest" as well (0.36.1 right now) , with node 16.20.1

@Minecraftschurli

This comment was marked as spam.

@alepouna
Copy link

This issue still happens, no official fixes yet?

@pkerschbaum
Copy link

Seems like I was able to apply a workaround for this problem: polyfilling require in ESM like this:

// File: "polyfill-require-in-esm.mjs"

/**
 * This ESM module polyfills "require".
 * It is needed e.g. when bundling ESM scripts via "@vercel/ncc" because of https://github.com/vercel/ncc/issues/791.
 */
import { createRequire } from 'node:module';
import url from 'node:url';

const __filename = url.fileURLToPath(import.meta.url);
globalThis.require = createRequire(__filename);
// File: "my-script.mjs"
import './polyfill-require-in-esm.mjs';

// now do everything else, importing other packages and stuff

@extravio
Copy link

extravio commented Sep 25, 2023

Seems like I was able to apply a workaround for this problem: polyfilling require in ESM like this:

I've tried your workaround but it didn't work for me unfortunately

I still get

This file is being treated as an ES module because it has a '.js' file extension and '/.../dist/status-check/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
    at eval (eval at 553 (file:///.../dist/webpack:/javascript-action/node_modules/@vercel/ncc/dist/ncc/@@notfound.js:1:1), <anonymous>:1:1)

@dforsber
Copy link

dforsber commented Jan 9, 2024

This helped me (gnu sed in OSX "is" gsed).

gsed -i 's/module=>{module.exports=eval("require")("")}/module=>{module.exports={}}/g' index.js 

@fregante
Copy link
Contributor

fregante commented Jul 29, 2024

I found this piece of code in my build:

module.exports = eval("require")("@actions/cache");

This happened because @actions/cache was not installed in my dependencies.

I suggest looking into your build for any require calls.

Either way NCC should not output such eval("require") calls in ESM envs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests