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

Sugary defaults: picking a default value for "main" #3

Closed
domenic opened this issue Mar 15, 2018 · 22 comments
Closed

Sugary defaults: picking a default value for "main" #3

domenic opened this issue Mar 15, 2018 · 22 comments

Comments

@domenic
Copy link
Collaborator

domenic commented Mar 15, 2018

As noted in one of the examples, we could choose a default value for "main", such as ${packageName}.js or index.mjs or similar.

Doing so seems fraught, in that the browser would be picking preferred file names and extensions for your files. Apart from favicon.ico, and maybe a few other cases I'm forgetting, the browser has never done this before---for good reason, I think.

(What about index.html, you might say? Nope, the browser knows nothing about that convention. That's purely the server choosing to respond to x/ with the on-disk-file x/index.html.)

But, I wanted to have a dedicated issue to discuss this.

@matthewp
Copy link

I like the idea of allowing "main" to be optional, giving the server the freedom to define its own conventions like it does with index.html. It might do filesystem searching for index.js, index.mjs, packageName.js, etc. Or it might choose to serve a different main depending on browser capabilities.

@bmeck
Copy link

bmeck commented Mar 15, 2018

If "main" is missing, is the intended behavior to resolve to a "directory"?

{
  "path_prefix": "/node_modules",
  "packages": {
    "moment": { },
  }
}
import('moment'); // `/node_modules/moment/` ?

If so, the server could do proper redirecting for the exports (using location:, or export *, {default}).

@justinfagnani
Copy link
Collaborator

I think a big problem with leaving this up to servers is tools interop.

A huge use-case for mappings is so that tools know where to locate files. If I set TypeScript's module resolution to "map", it should be able to completely resolve specifiers without relying on what a server might do if a specifier resolves to a directory.

@bmeck
Copy link

bmeck commented Mar 15, 2018

@justinfagnani I'm not sure I understand how resolving to the directory would not allow them to do that.

@justinfagnani
Copy link
Collaborator

Right, so I'm saying specifiers should not resolve to a directory.

@bmeck
Copy link

bmeck commented Mar 15, 2018

I disagree since most servers let you do redirects already and find it simpler than trying to form a pattern relying on a specific path name that might change over time (index.wasm could be the preferred pathname in the future!). Directories are not content-type specific, and already highly configurable.

@justinfagnani
Copy link
Collaborator

Leaving it up to the server just means that other tools can't reliably use the mapping. I think it also puts more complexity on tools generating mappings, because they need to be aware of what the server might do for directories as well.

What about a specific opt-in to defaults per scope? Since the top level of a mapping is a scope, it's a natural place, and doesn't require any opinion by the platform.

@bmeck
Copy link

bmeck commented Mar 15, 2018

@justinfagnani how would opt-in per scope be significantly different from just telling people to use "main". Each package that differs since there isn't a default means this suffers the lack of reliability for package authors just like you describe for tooling authors.

@justinfagnani
Copy link
Collaborator

Presumably, if there's benefit to a default at all, aside from nudging the package ecosystem to the same defaults, it would also apply to a top-level setting. If the only benefit is to push the ecosystem to a more standard package layout, then that should probably be debated explicitly - I suspect hotly.

Repeated "main": "index.js", strings in the package map will be noisy, but compress well, so I think the main advantage would be the ease in handwriting if most packages do use the same main filename. I'd like to see it be relatively easy to write mappings by hand, so this is somewhat important to me, but it depends both on having a default and the ecosystem converging.

@bmeck
Copy link

bmeck commented Mar 15, 2018

@justinfagnani there is a large focus on tooling usage in the README. I am not sure if this is the issue to have a discussion about if manually writing JSON configuration by hand should be a priority. Personally, I don't think writing mappings by hand is very important in any sizable application.

@matthewp
Copy link

I agree with @bmeck here, I don't think any defaults chosen are going to age very well given .mjs and .wasm as contenders.

@justinfagnani
Copy link
Collaborator

While handwritten maps might not be realistic for "sizable" applications, it's very feasible for small apps, snippets, demos, etc. The simpler the mapping is, the higher the threshold is for when writing without a tool is just too cumbersome.

@bmeck
Copy link

bmeck commented Mar 15, 2018

@justinfagnani Are you talking about simpler in terms of how verbose it is, or how many features that need to be learned? I don't think we should overly optimize for a feature if it only is largely targeting the creation of snippets, or demos. Even for small apps, dependency graphs are not tiny these days.

@guybedford
Copy link
Collaborator

It could be worth distinguishing between file and folder packages here:

// File package
{
  "path_prefix": "/node_modules",
  "packages": {
    // any request to package subpaths will throw
    "moment": 'moment/index.js'
  }
}

// Directory package
{
  "path_prefix": "/node_modules",
  "packages": {
    // resolving to the package main with no main given will throw
    "moment": { path: 'moment' }
  }
}

@domenic
Copy link
Collaborator Author

domenic commented Mar 15, 2018

Interesting, I don't think we previously considered the idea of omitting main causing a directory request with trailing slash (and thus letting servers pick their default). That seems pretty plausible to me. It sidesteps any file extension or conventional filename debates.

The downside is that then tools have to know what a server will do, but we've dealt with this sort of tooling/filesystem/servers mismatch before, notably with tools needing to use out of band data for figuring out if something is a module script or classic script. I think the ecosystem would be able to come up with a strong convention for those tools pretty quickly...

@guybedford's comment is also interesting, but I think I like #4 a bit better for that case, as it allows subpaths and doesn't require repeating the same package twice. Maybe that should split into a separate issue if he disagrees.

Tooling vs. hand-written may also be a good dedicated issue. I tend to see both sides, although I think #7 will be pretty important if we anticipate people actually not using a tool at all; without #7, you must manually sync your package map and your directory listing, which is not fun to do by hand.

@guybedford
Copy link
Collaborator

Ahh thanks I missed #4 somehow, will move discussion there.

Given that we have a nice sugar through #4, I'm actually against any sugar for mains as these configurations get complex very quickly in their edge cases - default logic will become difficult for users to follow. The simpler the better - sugar can always be added later but not taken away.

@medikoo
Copy link

medikoo commented Mar 19, 2018

I also don't think letting servers doing their pick on directory resolution is a good idea, as this simply would mean package names map is not single source of information for resolution rules, and that makes it not that portable.

It would be best if through package names map in all cases we resolve final file paths.


the idea of omitting main

Lack of main (when not having default), should be considered as error.

But having some defaults, would be great. Still they should not be set by a standard, instead we may allow them to be predefined in a map.

For example, let's assume an idealistic scenario, where we have flat structure of dependencies, and main for each package is index.js. I'd love this to be covered fully by map like:

{
  "path_prefix": "/node_modules",
  "packages": {
    "*": { "main": "index.js" }
  }
}

@ljharb
Copy link

ljharb commented Mar 19, 2018

Servers always will be doing that; there’s no way to prevent it. In other words, the package name map simply can never be the sole source of truth, due to the nature of the web.

That said i think some kind of nestable default (not *, since that’s a valid package name on disk) is a wonderful idea.

@medikoo
Copy link

medikoo commented Mar 19, 2018

Servers always will be doing that; there’s no way to prevent it

Yes server can always respond with content of bar.js when foo.js is requested. That's true, but that's the other story.

This concern is about directory paths, where we leave directory to file resolution to the server.
I think package name map should always have file paths as final results, as that we way do not force any resolution logic to server side (that may decrease portability of map significantly).

@matthewp
Copy link

I think portability has played out fine with index.html despite that being something that servers came up on their own. We arguably already have a "default main" in the JavaScript ecosystem today, so I don't think it's a concern that tools are not going to be able to adapt when a new config format allows ambiguity on that point.

Even if a default main was picked people could probably hack around it by doing something like "main": "".

@serapath
Copy link

Is there any other reason than "is has never been done before" that would suggest picking a default name for "main" is bad? I can only see benefits.

Doing so seems fraught, in that the browser would be picking preferred file names and extensions for your files. Apart from favicon.ico, and maybe a few other cases I'm forgetting, the browser has never done this before---for good reason, I think.

Just because it has never been done before doesn't mean it would be bad to do it.
I consider servers coming up with the convention of index.html a strong indicator for a missing standard, where it is not important what the standard decides, but just that there is one.

(What about index.html, you might say? Nope, the browser knows nothing about that convention. That's purely the server choosing to respond to x/ with the on-disk-file x/index.html.)

i think servers solved a problem that could have been avoided if browsers would just have specified a default.


When I first saw ${packageName}.js proposed it made me really happy. I really think this would reduce noise in a package map and it is better than index.js, because when i edit my code i really dislike many tabs called index.js, so the package name is so much better :-)

@domenic
Copy link
Collaborator Author

domenic commented Nov 2, 2018

This was always pretty unlikely, and in the new proposal is less necessary. Let's not do this.

@domenic domenic closed this as completed Nov 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants