`mainFields` should match behavior of `esbuild`
- Dominant language
- TypeScript
- Stars
- 11.3k
- Forks
- 275
- PR merge metrics
- No merged PRs in 30d
Description
## Description
in this library, `mainFields` is simply hardcoded to the below ([reference](https://github.com/egoist/tsup/blob/3e158674bdeb3d060404987e1b278fd7d21ccda1/src/esbuild/index.ts#LL221C15-L221C15))
```
mainFields:
platform === 'node'
? ['module', 'main']
: ['browser', 'module', 'main'],
```
Note that **order is important!** With this declaration, module will be preferred (even in `cjs` only builds) for node
`esbuild` publishes several guidelines for how `mainFields` is managed, relevant sections copied below ([reference](https://esbuild.github.io/api/#platform))
Browser:
> When the platform is set to **browser** (the default value):
...
The [main fields](https://esbuild.github.io/api/#main-fields) setting is set to browser,module,main but with some additional special behavior: if a package provides module and main entry points but not a browser entry point then main is used instead of module if that package is ever imported using require(). This behavior improves compatibility with CommonJS modules that export a function by assigning it to module.exports. If you want to disable this additional special behavior, you can explicitly set the [main fields](https://esbuild.github.io/api/#main-fields) setting to browser,module,main.
Node:
> When the platform is set to **node**:
...
The [main fields](https://esbuild.github.io/api/#main-fields) setting is set to main,module. This means tree shaking will likely not happen for packages that provide both module and main since tree shaking works with ECMAScript modules but not with CommonJS modules.
Neutral:
> When the platform is set to **neutral**:
...
The [main fields](https://esbuild.github.io/api/#main-fields) setting is empty by default. If you want to use npm-style packages, you will likely have to configure this to be something else such as main for the standard main field used by node.
For node specifically, notice that the order is `main,module` which is different than the hardcoded order in `tsup`
## Problem
Due to this hardcoding, it isn't possible for consumers to specify which order to resolve external dependencies in. Additionally, since it overrides the default behavior of `esbuild`, building a package with vanilla `esbuild` and later migrating to `tsup` can have unforeseen problems as different versions of the dependencies will be pulled in
A prominent example of this is a long running issue with `node-fetch` https://github.com/node-fetch/node-fetch/issues/450 where using the `main` field is necessary to ensure the package works in `cjs` builds.
## Proposal
`tsup` should either follow these rules, or pass nothing to allow `esbuild` to manage them under the hood based on the platform.
Thanks!
Contributor guide
Research direction
Start at src/esbuild/index.ts around the hardcoded mainFields setting referenced in the issue, then compare it with esbuild's platform guidance and the existing tsup configuration path. Done means the chosen behavior no longer imposes the problematic order and consumers can follow the intended esbuild resolution behavior or specify the order explicitly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- build-system
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100