evanw / evanw/esbuild

[Feature] Non-circular `build.resolve` strategy or `tsconfig` options available for `build.onResolve`

Open
#4,264 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

Currently there is some difficulty with manually resolving import paths in `build.onResolve`, unless a plugin does not hold an application-specific knowledge of import aliases. The only consistent way to resolve is actually to delegate resolving back to `esbuild` like so (as suggested by `evanw` in #2198):
```JavaScript
{
name: "plugin",
setup(build) {
build.onResolve({ filter: /any/ }, async (args) => {
if (args.pluginData?.defaultResolve) return;
const res = await build.resolve(args.path, { pluginData: { defaultResolve: true } });
// ... rest
});
}
}
```
This approach could be problematic since the called `.resolve` is passed through every present `build.onResolve` callback, so it's technically possible that another callback intercepts it and the call does not actually reach our specified callback, or is intercepted afterwards and the resolution mechanism does not default to the `esbuild`'s one. In case, a plugin is local to some codebase it's fine, however if it's a distributed npm package there is no sure way to enforce the correct behaviour.

Another thing is also that it creates a weird loop where (as I can assume):
- `esbuild` parses AST, discovers an import statement and calls `build.resolve`;
- provided `onResolve` callback is called, it invokes `build.resolve` again;
- callbacks are called again, provided callback skips resolution, import is resolved by a default mechanism;
- return back to initial `onResolve` call and proceed with the plugin's logic.

As far as I can see, 2 possible scenarios would be nice here:
1. Access to default `esbuild`'s import resolution mechanism, or it's meta info that is used to resolve paths (including tsconfig options) so that it is possible to consistenlty match `esbuild`'s resolution method.
2. More hacky in my opinion, but maybe less cumbersome - have an option for `build.resolve` that skips calling plugins' callbacks

Contributor guide

No contributing guide indexed for this repository

Research direction

The issue names the build.resolve and build.onResolve entry points but no implementation files or tests. Start by tracing nested onResolve dispatch during build.resolve, then compare the proposed default-resolution and callback-bypass approaches; done requires a decided API design covering plugin interception and tsconfig-based resolution.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, javascript, typescript
Domain
build-system, compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.