Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What should the new moduleResolution setting be called? #51714

Closed
andrewbranch opened this issue Dec 1, 2022 · 32 comments · Fixed by #51669
Closed

What should the new moduleResolution setting be called? #51714

andrewbranch opened this issue Dec 1, 2022 · 32 comments · Fixed by #51669
Assignees
Labels
Discussion Issues which may not have code impact Fix Available A PR has been opened for this issue

Comments

@andrewbranch
Copy link
Member

I’m looking for community feedback on the naming for #51669. For the full background on that PR, read #50152.

The short version is that it’s mostly designed for bundlers, but is also appropriate for runtimes like Bun, especially those that understand TypeScript natively. I initially wanted to avoid a very specific name like bundler that could prove to be a bad name in a few years if, say, a new wave of bundlers takes a very different approach to module resolution, or a new wave of runtimes are well-suited for the mode, or a huge number of projects use all-in-one frameworks like Next.js that are also well-suited for the mode but make it difficult to recognize what bundlers and runtimes and resolution features are actually in use.

The name I first proposed in #50152 was conventional, because it attempts to find the common ground shared by all the popular non-Node, non-Deno resolvers I surveyed. There was some concern that this could be read as a snub to Node, Deno, and other resolvers that implement strict resolution rules for ESM, so I revived hybrid from #29353. Both names are intentionally vague, but I’m rethinking whether that’s a good idea.

One potential mitigation for the name becoming a poor fit due to unpredictable future events is simply tacking the year onto the end: bundler2022. I don’t love this because if it turns out to be long-lived with the help of small, backward-compatible changes, it will falsely appear to grow increasingly outdated.

Let me know your thoughts and suggestions. 🚲🏠

@andrewbranch andrewbranch added the Discussion Issues which may not have code impact label Dec 1, 2022
@andrewbranch andrewbranch self-assigned this Dec 1, 2022
@andrewbranch andrewbranch added this to the TypeScript 5.0.0 milestone Dec 1, 2022
@MartinJohns
Copy link
Contributor

I vote for BundlyMcBundlerface.

@ljharb
Copy link
Contributor

ljharb commented Dec 1, 2022

From reading the recommended issue, it's still not clear to me what the target is, besides bun/esbuild.

I think that it's reasonable to have resolution modes that match platforms:

  • node
  • browser
  • deno
  • whatever else is popular enough to warrant inclusion

but also to have modes that match what users expect:

  • "what babel does", which i suspect by a large margin is what users expect
  • esbuild/bun
  • whatever else goes here

Are there more tools/bundlers that would use the proposed new mode that I missed?

@andrewbranch
Copy link
Member Author

Webpack, Parcel, Browserify, maybe Rollup (they call into us for resolution so it’s debatable), Vite, Next.js I think, which uses swc.

Babel does module resolution? I thought it only needs to care about one file at a time, specified via glob or something?

@ljharb
Copy link
Contributor

ljharb commented Dec 1, 2022

Babel transpiles to CJS, so it allows ESM to be authored omitting extensions, and "index", and it ends up working the same.

If it's all bundlers, then I think "bundler" is probably the right key - the only way that term would stop being accurate would be if the majority of bundlers all switched to something new - and there'd probably be a new term we all associated with that new thing anyways that would help you name the new mode.

@fatcerberus
Copy link

fatcerberus commented Dec 1, 2022

In that case, "what babel does" reduces to moduleResolution: "node" (i.e. pre-ESM Node resolution behavior).

@andrewbranch
Copy link
Member Author

andrewbranch commented Dec 1, 2022

If we’re splitting hairs, what Babel does is orthogonal to moduleResolution. The moduleResolution setting you should choose to check your code that you’ll later compile with Babel depends entirely on where you intend to run that CJS code. moduleResolution is only concerned with the things in your toolchain/runtime that actually consume module specifiers and perform resolution to take some action on the target module. The caveat is that if, as in Node, resolution happens differently depending on import/require syntax, file extension, and package.json scope, then TypeScript may need to understand that a transformation of import syntax is going to happen. So in the example of running code transpiled with Babel in Node 12+, you would want to choose moduleResolution: "nodenext" while ensuring that your package.json "type" is unset or set to "commonjs", so that TypeScript will understand that the import syntax will ultimately become a require. This all works out only because Babel will produce roughly the same JS that tsc would under these settings—TypeScript doesn’t know you’re using Babel or what Babel will do, but it’s sufficiently close to what tsc will do that the checking works out. But it would be wrong to use moduleResolution: "node" in this case, because that mode lacks support for package.json exports. So if you write an import of some package that Babel turns into a require of some package and then run that require in Node, Node will consult that package’s exports if it exists. If that lookup resolves to a different result than the main would have pointed to, then likewise you would get an incorrect resolution of types for that import under moduleResolution: "node". (To help clear this confusion up, I plan to rename node to node10 after #51669.)

@Faithfinder
Copy link

If this targets bun/rebuild you could name it both as an alias, and tack on a year anyway.

@johnnyreilly
Copy link

johnnyreilly commented Dec 2, 2022

Have you considered conventionalnext 😅

To be honest, hybrid doesn't feel like a great name as it doesn't convey any particular meaning. Is it for the browser? Don't know. Is it not for the browser? Maybe?

How about runtime? I think the idea is that this setting covers multiple runtimes including node, deno, bun etc. And bundlers are invoked by a runtime (typically node but that may change).

In my mind the advantage of runtime is that it conveys some information of where it might be used

And if you wanted to hedge your bets: runtimenext

And if you want internet points: runtimeyMcRuntimeFace

@fatcerberus
Copy link

If you're targeting a bundler, moduleResolution: "runtime" is inaccurate because where your code is ultimately run doesn't matter - the bundler does all module resolution, which in turn depends on the particular bundler, not the runtime it happens to run on. That's what this setting is about - it's not about where your code is being run, but instead which part of your toolchain resolves your module specifiers.

@robpalme
Copy link

robpalme commented Dec 2, 2022

I think the shared heritage for the new mode is that it captures descendents/specializations of a Node-like approach. It represents some kind of lowest common denominator for mainstream use today, which also means it omits some of the features of latest Node. Here are some suggestions:

  • node-based (dual use of "based")
  • node-compatible
  • node-minimal
  • node-like
  • node-ish
  • nodey (I genuinely like this)

All of these escape the value judgements of conventional and vagueness of hybrid. It's no more or less of a snub to Node or non-Node resolvers than today's situation in which they are forced to use node.

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Dec 2, 2022

What do people think about nodey-mcnodeface?

@fatcerberus
Copy link

Okay I’ll bite - is this a recent meme I’m not aware of?

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Dec 2, 2022

It's not very recent, but here's the context

@robpalme
Copy link

robpalme commented Dec 3, 2022

Perfect. Commit to the bit please 😉

@fatcerberus
Copy link

explodey-mcexplodingface and using it causes your computer to blow up

@frank-dspeed
Copy link

i vote for not even landing it till we refactored more parts of the existing system wait for nodejs 19.1 to stay for some time like 3 month at present existing experimental loader hooks get ported and that solve the resolve problem outside of ts it self.

@frank-dspeed
Copy link

frank-dspeed commented Dec 4, 2022

if you guess it is a improvement over the existing situation be brave land it as moduleResolution node at last thats what it is as node is hybrid by default and thats where all problems get caused by require supports 5+ resolve algos in a single function.

@frank-dspeed

This comment was marked as off-topic.

@jakebailey
Copy link
Member

I'm late to the party, but I think when this was first proposed I liked to think of this as being named permissive. It feels like what this mode is doing is basically just "let me do whatever all of the bundlers permit me to do and get out of my way" (at least in my mental model).

@DanielRosenwasser
Copy link
Member

I do think node being in the name makes sense. To me, node-flavored is reminiscent of GitHub Flavored Markdown (though I'm sorry in advance to the Brits who will accidentally write node-flavoured).

@fatcerberus
Copy link

fatcerberus commented Dec 5, 2022

The problem with permissive, to my mind, is, "permissive" with respect to what? If it's more permissive with respect to bundlers then that just means it's resolving things more closely to how bundlers do and isn't actually any more permissive than any other mode relative to the ecosystem; the goalposts are just as far away as they were before, they're just in a different spot now. For TS to actually be "more permissive" in any meaningful general sense it would have to (try to) support every module resolution strategy at once, which would almost certainly involve rewriting module specifiers.

@andrewbranch
Copy link
Member Author

andrewbranch commented Dec 6, 2022

node-based (dual use of "based")

I’m up for node-based for hybrid as long as I can also rename node to node-cringe

I agree that the features the new mode shares with Node resolution are its most distinctive traits—if you give a directory named node_modules special powers, you must share something significant with Node. Something that mentions node is probably the least likely to become a misnomer in the future. However, I worry that putting node in the name could easily be mistaken for a signal that the mode is suitable for people actually compiling for Node, when the only correct choices for them are node16 and nodenext. Pending the renaming of node to node10, I was excited about creating a situation where a Node user can look at our resolution options and pick the right one by name, without having to read a three-volume history on module systems and TypeScript options.

@johnnyreilly
Copy link

johnnyreilly commented Dec 6, 2022

"chapter 10: node and ES modules (not a short chapter)" 😅

I do think node being in the name makes sense. To me, node-flavored is reminiscent of GitHub Flavored Markdown (though I'm sorry in advance to the Brits who will accidentally write node-flavoured).

It's okay - we've had to get used to color instead of colour, not to mention all the zs that ought to be ss - we will survive another spelling mishap. 😉

In therapy news I've nearly made peace with the spelling of HTTP referer

Jokes aside, I think node-flavored actually carries intent quite well, and meaningful names are something to optimise for. (Or "optimize" for - YMMV)

@fatcerberus
Copy link

fatcerberus commented Dec 6, 2022

How did I never notice that referer was misspelled? And now I can’t unsee it… thanks I hate it

@nicojs
Copy link

nicojs commented Dec 7, 2022

How about node-worthy? (couldn't help myself 🤡).

So how about: node-convention?

I agree with the node-style of naming this one. But I also like "conventional", because it communicates that it could be used in multiple use cases as long as they support the convention. Using node-convention clearly communicates that the convention is based on "node". If you want to know more, you can dig into the docs.

@robpalme
Copy link

robpalme commented Dec 7, 2022

@andrewbranch said

I worry that putting node in the name could easily be mistaken for a signal that the mode is suitable for people actually compiling for Node

A stronger distinction would be to swap the order.

  • approximating-node (a formalized nodey)
  • like-node
  • akin-to-node
  • tantamount-to-node (may imply node is a crime)

@weyert
Copy link

weyert commented Dec 7, 2022

I think it would help to clarify how the existing module resolutions mode are working. Maybe I missed whole sections in the documentation but as far as I know only classic and node are documented [1]

At the moment it sounds like this new resolution mode is the behaviour most TypeScript developers would expect when messing around with type=module? No need to import directories with index.js, ability to use no file extension or instead the .ts? If so, the question is, how would a typical developer call such a mode 🤔

[1] https://www.typescriptlang.org/docs/handbook/module-resolution.html#module-resolution-strategies

@hubertkuoch
Copy link

Here my two cents but why not just moduleResolution: typescript?

With moduleResolution: node, TS follows Node module resolution, it can be seen as an external constraint that TS must implement to match with Node specifics.

Whereas, the new module emerged directly from TS usage itself and represents what the TS developer community has been doing to circumvent Node resolution specific constraints in a more or less hacky way (paths alias, typesVersions etc.) as @andrewbranch already described thoroughly.

Plus, it makes .ts extension resolution explicit in its name.

@fatcerberus
Copy link

fatcerberus commented Dec 10, 2022

Except that there's no such thing as "TypeScript module resolution" (unless TS rewrites import paths, which is a non-starter) because there's no "TypeScript runtime"--the closest thing to that would be Deno--and you're meant to always write the paths that work at runtime. The idea is that TS doesn't impose itself on you, but instead you configure TS to align with your target environment. TypeScript is a compiler, so not a target environment. Even if people are using paths, etc. then they also need to find a way to get their runtime and/or bundler to understand them, otherwise the code will fail at runtime. Whether TS can resolve the path or not is immaterial at that point.

@andrewbranch
Copy link
Member Author

Thanks for all the suggestions. I don’t think there’s a perfect option, but I’m currently leaning toward bundler. I had two concerns with this name:

  1. What if bundlers all decide to do something super different in the future? I’m encouraged by our progress on Flag Deprecation Plan #51000 and think that going forward, we’ll be able to change defaults with a process and time scale that neither leaves decade-old misnomers around nor breaks a huge number of consumers without warning. If bundler-based resolution evolves significantly, the process will probably go something like (1) new options added that can be enabled alongside --moduleResolution bundler, (2) a new mode named something like --moduleResolution bundler2022 aliased to bundler, (3) deprecation-style warnings that the settings implied by bundler will change, (4) updated defaults in bundler, old defaults in bundler2022. I also think it’s unlikely that the changes we’ll see will be so disruptive and backward-incompatible that such a heavy process will be necessary. Planning for the unknown is great, but I am pretty satisfied to cross this bridge if we ever get to it.
  2. The mode is good for more than just bundlers. At the moment, the only example I know of is Bun, and I don’t think a single example is enough to justify a more generic name right now. While I do think it’s quite possible we’ll see more JS runtimes emerge in the coming years, I have no basis for predicting whether this module resolution mode will be suitable for them. (Also, Bun has already changed part of its module resolution algorithm once since being released.) While there is nothing inherently bundler-specific about this mode, I would rather have a name now that makes it obvious that the mode is a good choice for bundler users and a bad choice for Node users, which together I think must be the vast majority of users today. I am concerned that an attempt to future-proof this will make it a present-hazard.

@johnnyreilly
Copy link

No nodey-mcnodeface!

@Conaclos
Copy link

What about node16-extended?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Discussion Issues which may not have code impact Fix Available A PR has been opened for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.