You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This PR introduces a new moduleResolution setting value called hybridbundler (see #51714), designed primarily for bundlers and runtimes that include a range of Node-like resolution features and ESM syntax, but do not enforce the strict resolution rules that accompany ES modules in Node or in the browser. Special consideration has also been given for bundlers and runtimes that understand TypeScript natively and do not require compilation to JavaScript by tsc before consumption. Additionally, resolution of package.json exports and imports can be enabled/disabled/customized in configuration options. This should allow users of different bundlers and runtimes with slight variations in resolution features to customize TypeScript’s resolution settings under bundler as appropriate.
✅ Application authors who use a bundler on their TS or JS files before a runtime consumes that bundle
✅ Application authors who run in Bun
✅ Library authors who use a bundler to deploy a UMD bundle
⚠️ Library authors who use a tool like Rollup to deploy multiple builds in different module formats—defer to advice from your build tool
🚫 Anyone intending to produce modules with tsc that will run in Node or the browser without further bundling or processing
🚫 Anyone intending to produce modules with tsc that will run in Deno without further bundling or processing
Comparison with existing module resolution settings
classic
node
node16
bundler
node_modules packages
✅
✅
✅
extensionless
✅
✅
CJS only
✅
directory index
✅
✅
CJS only
✅
*.ts imports
✅
package.json exports
✅
✅
exports conditions
always node, types; import from ESM, require from CJS; custom additions
always types, import; custom additions
Module syntax restrictions
--moduleResolution bundler does not support resolution of require calls. In TypeScript files, this means the import mod = require("foo") syntax is forbidden; in JavaScript files, require calls are not errors but only ever return the type any (or whatever an ambient declaration of a global require function is declared to return).
New compiler options
allowImportingTsExtensions: Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set.
resolvePackageJsonExports: Use the package.json 'exports' field when resolving package imports. Enabled by default in node16, nodenext, and bundler.
resolvePackageJsonImports: Use the package.json 'imports' field when resolving imports. Enabled by default in node16, nodenext, and bundler.
customConditions: Conditions to set in addition to the resolver-specific defaults when resolving imports. Valid in node16, nodenext, and bundler.
Open questions
Should resolvePackageJsonExports and resolvePackageJsonImports be disableable in node16 and nodenext? I see no valid reason to disable them in those modes, but I haven’t yet prohibited it.
There was no objection to leaving these toggleable.
I would like to consider allowing *.ts imports to resolve in every module resolution mode, or at least node16 and nodenext, to improve consistency and (importantly) portability of .d.ts files between modes. I think @weswigham has already done this in another open PR, so perhaps it won’t be too controversial.
I think this is doable but not necessary for merging; will follow up in a subsequent PR.
With four new resolution-specific compiler options, it would be nice to introduce hierarchy into tsconfig.json. That’s a non-trivial design discussion on its own, especially considering that tsconfig files can inherit from each other. Is it worth tackling that first / as part of this / in the same release cycle to avoid the expansion of root-level options here?
This was not considered a blocker when I mentioned it in a design meeting. If there is time to design this before 5.0 is released, we can move the new options accordingly.
Should bundler become the new default resolution mode for --module commonjs? I would like to rename node to node10 in a follow-up PR, and stop maintaining it going forward. It is not a good choice for anyone since Node 10 is long out of service.
@sandersn endorsed this mode being the new default. I will get more feedback in a subsequent PR.
@andrewbranch why does bundler apply the node export condition by default?
I've been trying to make a package with conditional exports that use node-fetch types for fetch, Response etc in node and Web API types otherwise, and it would be a lot easier to provide a good user experience if bundler, or some other mode, would not apply the node export condition. Because the only option is to tell users to set customConditions.
And node condition seems like a weird default for bundler since it's more common for bundlers to be used to deploy to web environments than to Node.
@jedwards1211 No problem. I assume you’re aware that Webpack, and I assume other bundlers too, do apply the node condition even though they’re not Node 🤦🏻♂️
I’m updating the tsconfig.json reference now. It’s very hard to include bundler in the Module Resolution handbook page without totally rewriting it, which I’m essentially already doing over at #52593.
mklein994
added a commit
to mklein994/playground-vue
that referenced
this pull request
Jul 11, 2023
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR introduces a new
moduleResolution
setting value calledhybrid
bundler
(see #51714), designed primarily for bundlers and runtimes that include a range of Node-like resolution features and ESM syntax, but do not enforce the strict resolution rules that accompany ES modules in Node or in the browser. Special consideration has also been given for bundlers and runtimes that understand TypeScript natively and do not require compilation to JavaScript bytsc
before consumption. Additionally, resolution of package.jsonexports
andimports
can be enabled/disabled/customized in configuration options. This should allow users of different bundlers and runtimes with slight variations in resolution features to customize TypeScript’s resolution settings underbundler
as appropriate.--moduleResolution hybrid
andrewbranch/TypeScript#2 for a diff between those two branchesexports
outside of Node #50794moduleResolution
setting be called? #51714Who should use this mode?
tsc
that will run in Node or the browser without further bundling or processingtsc
that will run in Deno without further bundling or processingComparison with existing module resolution settings
node_modules
packages*.ts
importsexports
exports
conditionsnode
,types
;import
from ESM,require
from CJS;custom additions
types
,import
;custom additions
Module syntax restrictions
--moduleResolution bundler
does not support resolution ofrequire
calls. In TypeScript files, this means theimport mod = require("foo")
syntax is forbidden; in JavaScript files,require
calls are not errors but only ever return the typeany
(or whatever an ambient declaration of a globalrequire
function is declared to return).New compiler options
allowImportingTsExtensions
: Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set.resolvePackageJsonExports
: Use the package.json 'exports' field when resolving package imports. Enabled by default innode16
,nodenext
, andbundler
.resolvePackageJsonImports
: Use the package.json 'imports' field when resolving imports. Enabled by default innode16
,nodenext
, andbundler
.customConditions
: Conditions to set in addition to the resolver-specific defaults when resolving imports. Valid innode16
,nodenext
, andbundler
.Open questions
resolvePackageJsonExports
andresolvePackageJsonImports
be disableable innode16
andnodenext
? I see no valid reason to disable them in those modes, but I haven’t yet prohibited it.*.ts
imports to resolve in every module resolution mode, or at leastnode16
andnodenext
, to improve consistency and (importantly) portability of .d.ts files between modes. I think @weswigham has already done this in another open PR, so perhaps it won’t be too controversial.bundler
become the new default resolution mode for--module commonjs
? I would like to renamenode
tonode10
in a follow-up PR, and stop maintaining it going forward. It is not a good choice for anyone since Node 10 is long out of service.