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

The Great Sigil Lottery #41

Open
jkrems opened this issue Aug 15, 2019 · 8 comments
Open

The Great Sigil Lottery #41

jkrems opened this issue Aug 15, 2019 · 8 comments

Comments

@jkrems
Copy link
Owner

jkrems commented Aug 15, 2019

Forked from #40 (comment).

We have three kinds of specifiers that people have asked for (implied: that we may or may not want to support):

  1. Getting the public interface of the package. This will allow people using exports to actually unit test their packages (since exports do not apply to relative specifiers). Examples: (the main/default export), ✩/subpath
  2. Adding custom aliases that are only valid inside of the package boundary. Examples: ✩data/emoji.json, ✩fetch.
  3. Accessing arbitrary paths relative to the package boundary. Examples: ✩/src/model.mjs.

Of these, only (1) and (3) actually conflict. (2) could share a symbol with either one of them. A concern raised by @guybedford was that if (1) and (2) share a symbol, it may be confusing.

So to me the options are:

  1. One sigil, no (3):
    • Use ~ and ~/ to mean "this package as if it was imported by name".
    • Allow ~<name> to be used for custom aliases within the package.
  2. Two sigils, optional support for (3):
    • Use ~ and ~/` to mean "this package as if it was imported by name".
    • Use #<name> for "private names", aliases only visible inside of the package.
    • (optional) Use #/ for "paths relative to the package boundary".

For packages that don't use exports, ~/ and #/ are effectively the same but that would change once they choose to remap subpaths and/or lock themselves down.

My preference right now would be ~ + # without support for importing non-public paths relative to the project root. There would still be design space for adding #/ in the future if it becomes truly necessary. Both ~ and # can be used as specifier prefixes since ESM only recognizes ./, ../, and / as valid relative URLs.

@jkrems
Copy link
Owner Author

jkrems commented Aug 15, 2019

But if we must then my preference would be to use ~/ for the internal root and #/ or something else for the public interface.

Under that logic, perhaps we should use ~name?

@guybedford

@ljharb
Copy link
Contributor

ljharb commented Aug 15, 2019

I'd prefer option 1, and force internals to be imported with relative paths (as opposed to with ~ or similar, ie, package-relative paths).

My preference right now would be ~ + #

do you mean to include the # here?

@jkrems
Copy link
Owner Author

jkrems commented Aug 15, 2019

do you mean to include the # here?

Yes, I think using a separate sigil for "internal alias" and "this package's public interface" makes sense. But I could also see myself interpreting ~ as a "magical default internal alias". In which case the same sigil seems fine.

@ljharb
Copy link
Contributor

ljharb commented Aug 15, 2019

I prefer to limit ourselves to as little magic as possible :-)

@guybedford
Copy link
Contributor

I've found myself thinking perhaps we shouldn't restrict private names to include a special symbol prefix.

The reason for this is that there may be cases where a user wishes to be able to use existing code that has a bare specifier import, and they want full control over its resolution locally.

For example, I might have a lot of legacy code that references import 'underscore' that I want to remap to import 'lodash' without having to update the code (for whatever reason that may be).

Since import maps provide the flexibility to do this, it feels to me like allowing the flexibility for users to do this as well may be very beneficial, and the restriction to a special character prefix would feel unnecessarily constraining.

@GeoffreyBooth
Copy link
Collaborator

Along those lines, I’d like to consider how we could align with the import maps proposal more generally. Like, is there any version of Node’s import maps implementation where Node can support a Web-style import map as is? Maybe if all paths are relative? It would be nice to say that Node simply supports import maps, or a subset of import maps that are compatible between Node and browsers, rather than Node supporting a separate thing that’s a lot like browser import maps but not interchangeable.

@ljharb
Copy link
Contributor

ljharb commented Aug 19, 2019

Considering browser import maps are far from finalized, that may not be too useful at this stage.

@jkrems
Copy link
Owner Author

jkrems commented Aug 19, 2019

@GeoffreyBooth I think supporting import maps natively is absolutely worth doing. But we do try to make node work with minimal tooling. Only supporting import maps would make it effectively impossible to use dependencies in ESM without a tool writing an import map. For me exports is there to encourage an ecosystem that has high quality metadata so that once import maps stabilize, we can support them without a long period of ecosystem catch-up.

@guybedford I agree. It may be worth calling out the pro/cons for having a sigil for imports. My best attempt right now:

  • 👍 Clearly marking indirection beyond the established "dependency name" provides a valuable signal for where to look and can make it easier to navigate code.
  • 👎 Requiring a sigil makes it impossible to support tools that don't support imports (including older versions of node).
  • 👎 It is inconsistent with the HTML restrictions on imports. People who know the browser standard may be surprised that a similar feature acts differently.
  • 👎 It is inconsistent with the existing browser field and similar mechanisms that allow overriding specifiers, including relative paths. They don't require a special prefix.

Let me know if I forgot arguments either way. And of course, quantity of bullet points in either direction isn't the thing that counts.

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

4 participants