privatenumber/tsx

Webpack loader broken on Node 20

fregante opened this issue · 7 comments

Bug description

This works on Node 18- but not on 20

cross-env NODE_OPTIONS="--loader tsx" webpack

Reproduction

npm init -y
npm install tsx webpack webpack-cli
echo 'export default {}' > webpack.config.ts
NODE_OPTIONS="--loader tsx" npx webpack

Node 20

(node:84039) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
[webpack-cli] Unable load './webpack.config.ts'
[webpack-cli] Unable to use specified module loaders for ".ts".
[webpack-cli] Cannot find module 'ts-node/register' from '.'
[webpack-cli] Cannot find module 'sucrase/register/ts' from '.'
[webpack-cli] Cannot find module '@babel/register' from '.'
[webpack-cli] Cannot find module 'esbuild-register/dist/node' from '.'
[webpack-cli] Cannot find module '@swc/register' from '.'
[webpack-cli] Please install one of them

Node 18

 NODE_OPTIONS="--loader tsx" webpack
(node:84137) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:84137) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:84137) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:84137) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
assets by status 99 bytes [cached] 1 asset

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

ETC..
ETC..
ETC..

Environment

System:
    OS: macOS 13.4.1
    CPU: Intel i9
    Memory: 138.69 MB / 16.00 GB
    Shell: 3.6.1 - /usr/local/bin/fish
  Binaries:
    Node: 20.1.0 - /usr/local/bin/node
    Yarn: 1.22.11 - /usr/local/bin/yarn
    npm: 9.6.4 - /usr/local/bin/npm
  npmPackages:
    tsx: ^3.12.7 => 3.12.7

Can you work on a fix?

  • I’m interested in opening a pull request to address this issue.

Note that this appears to be a common Node 20 issue:

I also reported it on webpack’s repo:

Thanks for your issue.

But I'm actually unable to reproduce the same error you're getting. Can you provide a repository link so I can easily reproduce it? I think I'm either missing files or getting the wrong dependency versions.

> node -v
v18.18.2

> NODE_OPTIONS="--loader tsx" npx webpack
(node:46393) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:46393) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:46409) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:46409) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:46409) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:46409) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
assets by status 99 bytes [cached] 1 asset

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

ERROR in main
Module not found: Error: Can't resolve './src' in '/Users/pn/Desktop/test-tsx-279'
resolve './src' in '/Users/pn/Desktop/test-tsx-279'
  using description file: /Users/pn/Desktop/test-tsx-279/package.json (relative path: .)
    Field 'browser' doesn't contain a valid alias configuration
    using description file: /Users/pn/Desktop/test-tsx-279/package.json (relative path: ./src)
      no extension
        Field 'browser' doesn't contain a valid alias configuration
        /Users/pn/Desktop/test-tsx-279/src doesn't exist
      .js
        Field 'browser' doesn't contain a valid alias configuration
        /Users/pn/Desktop/test-tsx-279/src.js doesn't exist
      .json
        Field 'browser' doesn't contain a valid alias configuration
        /Users/pn/Desktop/test-tsx-279/src.json doesn't exist
      .wasm
        Field 'browser' doesn't contain a valid alias configuration
        /Users/pn/Desktop/test-tsx-279/src.wasm doesn't exist
      as directory
        /Users/pn/Desktop/test-tsx-279/src doesn't exist

ERROR in main.js
main.js from Terser plugin
__name is not defined
ReferenceError: __name is not defined
    at terserMinify (eval at transform (/Users/pn/Desktop/test-tsx-279/node_modules/terser-webpack-plugin/dist/minify.js:2:448), <anonymous>:4:361)
    at minify (/Users/pn/Desktop/test-tsx-279/node_modules/terser-webpack-plugin/dist/minify.js:22:10)
    at Object.transform (/Users/pn/Desktop/test-tsx-279/node_modules/terser-webpack-plugin/dist/minify.js:43:10)
    at execFunction (/Users/pn/Desktop/test-tsx-279/node_modules/jest-worker/build/workers/threadChild.js:148:17)
    at execHelper (/Users/pn/Desktop/test-tsx-279/node_modules/jest-worker/build/workers/threadChild.js:127:5)
    at execMethod (/Users/pn/Desktop/test-tsx-279/node_modules/jest-worker/build/workers/threadChild.js:131:5)
    at MessagePort.messageListener (/Users/pn/Desktop/test-tsx-279/node_modules/jest-worker/build/workers/threadChild.js:49:7)
    at [nodejs.internal.kHybridDispatch] (node:internal/event_target:757:20)
    at exports.emitMessage (node:internal/per_context/messageport:23:28)

webpack 5.89.0 compiled with 2 errors and 1 warning in 210 ms

Your logs say node 18, but the issue appears on node 20. Your node 18 logs match mine (which are clipped). The errors that come after are fine, it's the parsing that's the problem.

I tried both. Same error with Node.js 20:

$ node -v
v20.9.0

$ NODE_OPTIONS="--import tsx" npx webpack
assets by status 99 bytes [cached] 1 asset

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

ERROR in main
Module not found: Error: Can't resolve './src' in '/Users/pn/Desktop/test-tsx-279'
resolve './src' in '/Users/pn/Desktop/test-tsx-279'
  using description file: /Users/pn/Desktop/test-tsx-279/package.json (relative path: .)
    Field 'browser' doesn't contain a valid alias configuration
    using description file: /Users/pn/Desktop/test-tsx-279/package.json (relative path: ./src)
      no extension
        Field 'browser' doesn't contain a valid alias configuration
        /Users/pn/Desktop/test-tsx-279/src doesn't exist
      .js
        Field 'browser' doesn't contain a valid alias configuration
        /Users/pn/Desktop/test-tsx-279/src.js doesn't exist
      .json
        Field 'browser' doesn't contain a valid alias configuration
        /Users/pn/Desktop/test-tsx-279/src.json doesn't exist
      .wasm
        Field 'browser' doesn't contain a valid alias configuration
        /Users/pn/Desktop/test-tsx-279/src.wasm doesn't exist
      as directory
        /Users/pn/Desktop/test-tsx-279/src doesn't exist

ERROR in main.js
main.js from Terser plugin
__name is not defined
ReferenceError: __name is not defined
    at terserMinify (eval at transform (/Users/pn/Desktop/test-tsx-279/node_modules/terser-webpack-plugin/dist/minify.js:2:448), <anonymous>:4:361)
    at minify (/Users/pn/Desktop/test-tsx-279/node_modules/terser-webpack-plugin/dist/minify.js:22:10)
    at Object.transform (/Users/pn/Desktop/test-tsx-279/node_modules/terser-webpack-plugin/dist/minify.js:43:10)
    at execFunction (/Users/pn/Desktop/test-tsx-279/node_modules/jest-worker/build/workers/threadChild.js:148:17)
    at execHelper (/Users/pn/Desktop/test-tsx-279/node_modules/jest-worker/build/workers/threadChild.js:127:5)
    at execMethod (/Users/pn/Desktop/test-tsx-279/node_modules/jest-worker/build/workers/threadChild.js:131:5)
    at MessagePort.messageListener (/Users/pn/Desktop/test-tsx-279/node_modules/jest-worker/build/workers/threadChild.js:49:7)
    at [nodejs.internal.kHybridDispatch] (node:internal/event_target:807:20)
    at exports.emitMessage (node:internal/per_context/messageport:23:28)

webpack 5.89.0 compiled with 2 errors and 1 warning in 81 ms

I get the error you're reporting without tsx though:

$ node -v
v20.9.0

$ npx webpack
[webpack-cli] Unable load '/Users/pn/Desktop/test-tsx-279/webpack.config.ts'
[webpack-cli] Unable to use specified module loaders for ".ts".
[webpack-cli] Cannot find module 'ts-node/register' from '/Users/pn/Desktop/test-tsx-279'
[webpack-cli] Cannot find module 'sucrase/register/ts' from '/Users/pn/Desktop/test-tsx-279'
[webpack-cli] Cannot find module '@babel/register' from '/Users/pn/Desktop/test-tsx-279'
[webpack-cli] Cannot find module 'esbuild-register/dist/node' from '/Users/pn/Desktop/test-tsx-279'
[webpack-cli] Cannot find module '@swc/register' from '/Users/pn/Desktop/test-tsx-279'
[webpack-cli] Please install one of them

I'm closing this as it doesn't seem to be a tsx issue.

Please provide a minimal reproduction when opening an issue next time so we save each other time.

Please provide a minimal reproduction when opening an issue next time so we save each other time.

Uh, I didn't? There's a section called "reproduction" and it shows the exact issue I'm talking about.

I get the error you're reporting without tsx though:

Yeah, that's why I used tsx, to fix the error. It's a regression between Node 18 and 20.

What happened is that between three months ago and now probably either node or webpack addressed the issue, but I don’t think the mistake here is on my part, as the report is extremely clear and minimal.

The solution here comes from a message that a later Node version added:

node:internal/process/esm_loader:48
      internalBinding('errors').triggerUncaughtException(
                                ^
Error: tsx must be loaded with --import instead of --loader
The --loader flag was deprecated in Node v20.6.0

This appears to work:

NODE_OPTIONS="--import tsx" npx webpack

I'm not here to cast blame and I agree that the issue looked great when I first saw a few weeks ago. But trying it today, I was unable to reproduce it, and I wasted a lot of time trying to understand the problem. So to me, this is effectively the same as no reproduction.

Ideally, your reproduction included a package.json or lock file so it can be reproduced without environmental issues (3rd party dependency updates) affecting it. Amongst the issues that are reported, what's been working best for me is when people provide a minimal reproduction as repository where I can clone and just run npm i; npm start.

Personally, I'm skeptical that there was a tsx issue at all; and I'm happy to be proven otherwise with a minimal reproduction repository link. If the result you get under "Node 20" is unexpected behavior, and I still get it with npx webpack directly on Node 20, was anything actually fixed?

The solution here comes from a message that a later Webpack or Node version added:

That message is from tsx, and --import tsx is what I used in the command above to show that it doesn't work for me with v20.9.0 (also included in the snippet).