Closed
Description
ES Modules in Node
https://gist.github.com/weswigham/22a064ffa961d5921077132ae2f8da78
Resolution Settings
- Last meeting:
exports
,types
,typesVersions
types@VERSION_SPECIFIER
moduleResolution
flagnode12
module
target flag?node
- Uhhhh but...
that could changealready does exist and changed. - Let's say it does change in the future - how do you opt into the old behavior?
- Is there potential for shifting behavior to "bork" an existing program?
- Uhhhh but...
- So
node12
as well?- Should have these match.
- What about a rolling
node-esm
flag that accumulates more?node-next
?node14
could come out, etc. sonode-next
could be that rolling target.- Is there an official name?
- No, it's just an update in the docs really.
- Could ask for a name?
- The name is there, it's Node 12 😄
- Could
module
andmoduleResolution
be one flag?module
toggles a specificmoduleResolution
- Do we need a new
moduleResolution
flag?- Yeah.
- Is
node
backwards-compatible?- Ehhh, they layer on the existing behavior.
- But if you continue following the existing resolution rules (e.g.
main
field inpackage.json
), you'll get the wrong behavior.
- Kind of weird that
package.json
s have more and more of our configuration. - Sounds like
node12
for both- Eventually
node-next
ornode-esm
or something along those lines.
- Eventually
- So
"module": "node12"
implies"moduleResolution": "node12"
.
Emit
- Implementation strategy: don't want to ship in stable with a partial implementation - lots of moving parts.
- What other things do we have to support?
.cjs
.mjs
- Unfortunate reality in Node.
- Potentially not used all that often, but users keep asking about them even though there's
"type": "module"
.- Under that, we have a path forward for
.ts
->.js
which is still good.
- Under that, we have a path forward for
- But still need
.mjs
output. So.mts
?- What about
.mtsx
?- What if you just have
.mts
?-
.mts
just supports JSX, doesn't support<AngleBracketCastSyntaxOn>values
-
Also type parameter lists with no constraint or trailing comma.
const f = <T>(t: T) => {}; // no good, have to rewrite as const f = <T extends unknown>() => {} const f = <T,>() => {}
-
What about
.tsx
for modules?- Well, doesn't generate an
.mjs
.
- Well, doesn't generate an
-
API isn't set up to disambiguate.
-
- Feels bad to say "JSX is allowed in this file."
.mtx
? 🤯- Supporting multiple extensions: we can do that, but we have special support
include
andexclude
globs being specialized for TypeScript. Already got burned by this withJSON
files. - How realistic would it be for us to say "no
.mts
and.cts
"?- Probably for a bit, but we would inevitably get demand.
- Still could start with something prescriptive. Maybe don't do it until we get an absolute need, along with a better sense of how people will organize their projects.
- Our own experience: sometimes when you're in ESM fully, with
"type": "module"
, you'll end up with times that you want to break out.- If you want to use native ESM with Electron, you need to break out and jump into CJS land to get
require
- Maybe
.cts
is more important than.mts
. - Is there a way to say "this is CJS in a
package.json
?"- Nope.
- You can put it in a sub-folder with a
package.json
that says"type": "whatever-is-not-module"
.
- If you want to use native ESM with Electron, you need to break out and jump into CJS land to get
- What if you just have
- What about
- File extension madness! Can't imagine the cost of
.cts
,.cd.ts
, etc.- We already use
readDirectory
, luckily it's not too bad anymore.
- We already use
- Luckily, a lot of resolution "just works" today but we need module disambiguation with modules.
- We can start working on this, but we will not ship until we feel feature-complete. ✅
Performance
- Our team has been working hard off thinking about how to help speed up TypeScript, and to help big projects scale.
- Lots of anecdotes
- One internal team switched from 1100 projects to way fewer. Hour-long compilation goes from 10 minutes.
- Massive React projects that use project references.
- Much of the time, projects incorrectly set up. Our bad, we had poor docs.
- Often look for hot spots in check time - didn't see it.
- React's
ComponentProps
- maybe takes 500ms to check?- If you have 100 projects that have to re-check this thing over and over, that's like 50 seconds on that one declaration alone.
- Declaration emit
- Checking + transforms
- Also,
--incremental
/--watch
needs to compute shape. Declaration emit happens twice. Initial build mode build emits twice #43995.- Idea: Can we cache the result of
typeToTypeNode
? #44043, Fix logic for determining whether to simplify keyof on mapped types #44042 - We now do some caching, cache and clone the nodes of declaration (Cache accessibe symbol chains and serialized type parameter name generation #43973)
- Idea: Can we cache the result of
- Found that a lot of anonymous generated types are massive. A lot of duplicated text. Idea: Can declaration emit synthesize imports? #44044.
- Feels weird to add
imports
that weren't there. import type
, bam, make everyone feel better.
- Feels weird to add
- Feels like we conflate a lot in declaration files.
- React's
- One codebase used this huge set of path mappings - 1800 of them.
- We were re-checking the mappings over and over and over again. Now we cache the patterns.
- Cache parsed path mapping patterns #44078
- Normalizing slashes - one massive codebase does it 3 million times, 2 seconds total on its own, generates a ton of garbage
- But MOST paths always have correct slashes, and on Unix they're ALWAYS the same.
- Basically, just see if you can skip that work ahead of time.
- Normalizing paths - removing relative intermediate components of paths.
- Kick out of normalizePath if there's nothing to do #44173
- Our regex was wrong.
- Seeing if we need to even process these paths before splitting etc. gives a 5% boost in project load across codebases.
- Been using pprof
- Basically the same info as the regular profiler, but its internal format actually allows you to handle longer profiling runs.
- Also some visualizer properties.
- Seems to have bugs on recursive functions though!