Skip to content
This repository has been archived by the owner on Sep 2, 2023. It is now read-only.

Subpath extension patterns and wildcard expansions #535

Closed
guybedford opened this issue Jul 21, 2020 · 9 comments
Closed

Subpath extension patterns and wildcard expansions #535

guybedford opened this issue Jul 21, 2020 · 9 comments

Comments

@guybedford
Copy link
Contributor

With package exports, it is ambiguous whether users should use extensions, as the author can define whatever they like:

{
  "exports": {
    "./feature.js": "./dist/feature.js",
    "./feature": "./dist/feature.js"
  }
}

as a result it seems likely that packages will have their own preferences here and we might see mixed patterns, unless we want to try and create some wider guidance.

Question: Should we encourage package authors to use extensions or not in subpaths for exports?

Furthermore, when using path exports it means that packages absolutely have to use extensions since:

{
  "exports": {
    "./features/": "./dist/features/"
  }
}

requires each pkg/features/x.js subpath to have an explicit extension.

One might argue that explicitly listing the exports could be an alternative here, but for example I recently provided an exports PR to a package with hundreds of individual components here - carbon-design-system/carbon-web-components#443.

In this case, the package absolutely must require its users to use extensions, and that is the only option practically.

Question: Are we ok with packages therefore having reason to sometimes have users use extensions in subpaths and sometimes not?

One thought here is that if a package wanted to maintain an extensionless interface, we could support this via a wildcard expansion of exports:

{
  "exports": {
    "./features/": "./dist/features/*.js"
  }
}

This would effectively be a sugar for globbing the RHS and treating it as if each entry were a separate entry in exports, but helps when there are hundreds that would be impractical to manually maintain.

When it comes to interop with import maps, the pattern would be that the import map only needs to include those mappings actually in use by the app - just because a component lib has 100s of components, doesn't mean you necessarily need every single one.

The risk is the complexity of users not necessarily knowing the difference beteween path exports and wildcard expansions when it comes to the import map implications.

Question: Would wildcard expansions be a useful feature for encouraging extensionless subpath patterns?

@ljharb
Copy link
Member

ljharb commented Jul 21, 2020

I don't think we want to encourage directory exports at all, because that drastically expands the API surface for CJS.

For reference, all of my packages omit the extension in "exports" (or will omit it, once they add "exports"), and won't allow any use of extensions to access their internals.

I'm super on board with some way to statically convey "always extensions" or "never extensions" to make import maps, and "exports" boilerplate, smaller - but I would hope whatever we come up with doesn't involve directory exports.

@guybedford
Copy link
Contributor Author

@ljharb did you see the example PR I linked there? SVG icon and component libraries absolutely have to rely on path exports, which is exactly the main issue at hand for having extension imports.

@guybedford
Copy link
Contributor Author

Specifically, see for example the icons folder here - https://unpkg.com/browse/[email protected]/es/icons/, where each folder is explicitly exported separately.

@guybedford guybedford added the modules-agenda To be discussed in a meeting label Jul 21, 2020
@ljharb
Copy link
Member

ljharb commented Jul 21, 2020

Sorry, I hadn't clicked through yet. I don't mean to suggest such a setting would be broader than "package level".

Re that specific PR/package, we don't have a better solution than "list every single one explicitly", since the tradeoff for the directory export is pretty large. It seems worth spending time on trying to find a better solution for it than a directory export, and all that entails.

@guybedford
Copy link
Contributor Author

No problem, just want to be sure we're on the same page with the use case. So the proposal I'm making in this issue is for wildcard expansions:

{
  "exports": {
    "./features/": "./features/*.js"
  }
}

where the * wildcard is like a globbed expansion into separate exports entries internally so that pkg/features/x resolves to features/x.js.

@guybedford
Copy link
Contributor Author

To give some more examples of the expansion and replacement syntax:

{
  "exports": {
    "./icons/": "./icons/*/index.js",
    "./features/": "./features/*/*.js"
  }
}

would support pkg/icons/x resolving into ./icons/x/index.js and pkg/features/y resolving into ./features/y/y.js.

@bmeck
Copy link
Member

bmeck commented Jul 21, 2020

I'm very intrigued by templating in these positions. I would need more time to think on it though.

@guybedford
Copy link
Contributor Author

I've created a PR for this feature in nodejs/node#34718 for further discussion.

@MylesBorins
Copy link
Contributor

This landed closing

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants