yao-pkg / pkg

Package your Node.js project into an executable
https://www.npmjs.com/package/@yao-pkg/pkg
MIT License
312 stars 11 forks source link

Can't require @apollo/server in node20 #10

Closed shouchechengadv closed 6 months ago

shouchechengadv commented 8 months ago

What version of pkg are you using?

5.11.0

What version of Node.js are you using?

20.10.0

What operating system are you using?

Windows, Ubuntu 22.04

What CPU architecture are you using?

x86_64

What Node versions, OSs and CPU architectures are you building for?

node20-win-x64, node20-linux-x64

Describe the Bug

After require('@apollo/server'), an error is thrown when executing the executable created by pkg. However, node main.js runs without any errors.

Error [ERR_REQUIRE_ESM]: require() of ES Module C:\snapshot\my-yao-pkg\node_modules\@apollo\server\dist\cjs\index.js from C:\snapshot\my-yao-pkg\main.cjs not supported.
index.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead either rename index.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in C:\snapshot\my-yao-pkg\node_modules\@apollo\server\package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).

    at Module.require (pkg/prelude/bootstrap.js:1851:31)
    at Object.<anonymous> (C:\snapshot\my-yao-pkg\main.cjs)
    at Module._compile (pkg/prelude/bootstrap.js:1930:22) {
  code: 'ERR_REQUIRE_ESM'
}

Expected Behavior

no errors

To Reproduce

  1. create main.js file and npm install @apollo/server
    // main.js
    console.log(require('@apollo/server'))
  2. npx pkg main.js --target node20-win-x64
  3. excute main.exe
  4. ERR_REQUIRE_ESM error
robertsLando commented 8 months ago

ESM are not supported

shouchechengadv commented 8 months ago

@apollo\server support ESM and CommonJS. The error message indicates that the require JS file is CommonJS format. (@apollo\server\dist\cjs\index.js) The same code runs without any errors in node18-win-x64.

shouchechengadv commented 8 months ago

I found a simple solution to solve this problem, which is to add **/package.json to the pkg assets.

// package.json
{
  "pkg": {
    "assets": ["**/package.json"]
  }
}

The reason is that when Node.js parses files with the .js extension, it looks for the nearest package.json file to determine whether it is ESM or CommonJS.

Although @apollo/server has set @apollo\server\dist\cjs\package.json for @apollo\server\dist\cjs\index.js, pkg does not include it in the snapshot.

// @apollo\server\dist\cjs\package.json
{"type":"commonjs"}

As a result, it reads @apollo\server\package.json, which has "type": "module", causing the ERR_REQUIRE_ESM error.

I'm not sure why node18-win-x64 doesn't encounter the same problem.

robertsLando commented 8 months ago

Could you track this bug in the code and submit a PR to fix it? Could be an error with the resolver

davidmwhynot commented 7 months ago

@robertsLando I've not contributed to this project in the past but we ran into this issue today and I'd like to do what you suggested and track this down. However, I'm unsure what you're referring to when you say "resolver".

robertsLando commented 7 months ago

@davidmwhynot Did you tried with latest pkg version?

Infern1 commented 6 months ago

I found a simple solution to solve this problem, which is to add **/package.json to the pkg assets.

// package.json
{
  "pkg": {
    "assets": ["**/package.json"]
  }
}

The reason is that when Node.js parses files with the .js extension, it looks for the nearest package.json file to determine whether it is ESM or CommonJS.

Although @apollo/server has set @apollo\server\dist\cjs\package.json for @apollo\server\dist\cjs\index.js, pkg does not include it in the snapshot.

// @apollo\server\dist\cjs\package.json
{"type":"commonjs"}

As a result, it reads @apollo\server\package.json, which has "type": "module", causing the ERR_REQUIRE_ESM error.

I'm not sure why node18-win-x64 doesn't encounter the same problem.

This was also a fix for using tslog https://github.com/fullstack-build/tslog

Tried with pkg 5.11.3

robertsLando commented 6 months ago

The problem I think is due to resolve module not supporting ESM modules, related issue: https://github.com/browserify/resolve/issues/222

We are actually using it in lib/wolker.ts follow function: https://github.com/yao-pkg/pkg/blob/2fb1e1264a685050d3ad8100ce3c8a0b4d013381/lib/follow.ts#L37.

I tried to replace it long time ago but without success

robertsLando commented 6 months ago

Dup of https://github.com/yao-pkg/pkg/issues/16#issuecomment-1945486658