evanw / evanw/esbuild

Could not resolve file without extension from node_modules when using ts and tsx loader for js files

Open
#3,934 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
40.1k
Forks
1.3k
PR merge metrics
No merged PRs in 30d

Description

I have a very specific problem regarding ts and tsx loader and imports from node_modules that do not have extension specified.
Steps or files to reproduce:

package.json:
```
{
"name": "esbuild-test",
"main": "app.js",
"scripts": {
"build": "node build.mjs"
},
"devDependencies": {
"esbuild": "^0.24.0"
},
"dependencies": {
"core-js": "^3.38.1",
"regenerator-runtime": "^0.14.1"
}
}
```

app.jsx:
```
import 'core-js/stable'
//import 'regenerator-runtime/runtime'

console.log('Hello world!');
```

build.mjs:
```
import esbuild from 'esbuild'

await esbuild.build({
entryPoints: ['app.jsx'],
outfile: 'output.js',
bundle: true,
loader: {
'.jsx': 'tsx',
'.js': 'ts',
},
})
```

When I run `node build.mjs` I get this error: `Could not resolve "core-js/stable"`.
Seems like a problem with resolving file `index.js` in `core-js/stable` folder. If I specify this file directly it works, but then it fails to resolve other imports form this file.

Likewise, if I import a file from `node_modules` without extension - in my case it was `import 'regenerator-runtime/runtime'` - the build fails with `Could not resolve "regenerator-runtime/runtime"` but if I provide full file name with extension `import 'regenerator-runtime/runtime.js'`, it works.

By gradual elimination and trial-error method I discovered, that it may have something to do with `tsx` and `ts` loader. If I comment out either `'.jsx': 'tsx'` or `'.js': 'ts'` line from build.mjs the resolution and build works.
However, I need tsx transformation, because of experimental decorators that we are using through all of our project.

This also happes when I import some library which has a file without extension in its `"main"` field in `package.json`
(eg. `"main": "es/index"`)

Interestingly, this setup was working in esbuild 0.19.* and stopped working in 0.20 (tested also all newer versions but without success). So I assume it may have something to do with 'Reorder implicit file extensions within node_modules' [change in 0.20.0](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md#0200)

I also tested multiple node versions 19, 20, 21, 22 all with the same results.

Please, can you confirm if this is a bug or just some incorrect setting, in which case please point me to the right direction.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by running the provided node build.mjs reproduction with esbuild 0.20+ and compare it with 0.19.*. Inspect the resolver behavior around extensionless imports in node_modules and the 0.20.0 changelog entry “Reorder implicit file extensions within node_modules.” Done means both ts and tsx loaders resolve the shown core-js and regenerator-runtime imports without requiring explicit extensions.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, javascript, typescript
Domain
build-system, compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.