vercel / ncc

Compile a Node.js project into a single file. Supports TypeScript, binary addons, dynamic requires.
https://npmjs.com/@vercel/ncc
MIT License
9.1k stars 288 forks source link

Issue with ESM and node:protocol #789

Open sinedied opened 2 years ago

sinedied commented 2 years ago

I'm working on a Node.js project using ESM modules, and after bundling with ncc I have errors with imports using the node: protocol:

internal/modules/cjs/loader.js:885
  const err = new Error(message);
              ^

Error: Cannot find module 'node:fs'
Require stack:
- /Users/sinedied/projects/publish-devto/dist/index.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:885:15)
    ...

Tracing back the error, it seems that it's due to these generated imports: __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:fs")

It seems that node imports using this protocol leads to incorrect import generation. If I do a search & replace to remove the node: prefix from the output, the code works fine though.

Note that I have no way to alter these node: imports as they come from dependencies.

Did I missed something or it an issue with ncc?

styfle commented 2 years ago

I was able to reproduce with a index.mjs containing import fs from 'node:fs'; console.log(typeof fs); which outputs:

import { createRequire as __WEBPACK_EXTERNAL_createRequire } from "module";
/******/ "use strict";
/******/ /* webpack/runtime/compat */
/******/
/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = new URL('.', import.meta.url).pathname.slice(import.meta.url.match(/^file:\/\/\/\w:/) ? 1 : 0, -1) + "/";
/******/
/************************************************************************/
var __webpack_exports__ = {};

;// CONCATENATED MODULE: external "node:fs"
const external_node_fs_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:fs");
;// CONCATENATED MODULE: ./index.mjs

console.log(typeof external_node_fs_namespaceObject)

Seems like webpack is incorrectly turning the import into require()

styfle commented 2 years ago

Looks like webpack always emits CJS for node: for some reason

https://github.com/webpack/webpack/pull/12693

Looks like it needs Node.js 16 or newer.