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

Add proposal for pkg: dependency imports #3

Closed
wants to merge 43 commits into from
Closed

Conversation

jamesnw
Copy link

@jamesnw jamesnw commented Jun 30, 2023

Description

Draft PR for a design for locating and loading Sass files from “pkg:” URLs with platform-specific semantics.

@jgerigmeyer
Copy link
Member

the reader where to find the file.

While the Dart Sass implementation allows for the use of the `package:` url
scheme, a similar standard doesn't exist in Node. We could add `node_modules` to
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other major issue with node_modules is that a single file may have access multiple node_modules directories, and what's more different files may have access to different node_modules directories within the same compilation.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 14b5df6

the load path, but that again suffers from lack of clarity to the implementation
and the reader.

Some npm packages have adopted a convention of declaring their Sass entrypoints
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a logical separation between design concerns for the platform-agnostic pkg: syntax and design concerns for the Node.js-specific package importer. Consider adding a heading here to visually separate out the latter.

currently does not provide a native way to set a condition on a single
invocation of `require.resolve`, meaning we would need to implement our own
`package.json` parsing similar to [Rollup] or add a dependency on a community
solution like [resolve.exports]. However, this proposal will not prevent future
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not intrinsically opposed to using something community-standard like resolve.exports, especially since it's so small.

Comment on lines 89 to 92
A potential source of confusion is in instances where a dependency defines a
default or main export that is not in the root folder. In these cases, Sass will
look for index and partial files in the same folder as the default or main
export, and not in the package root.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this refer to a default or main JS export?

Can you document the reasoning behind this design decision as well?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be for any file defined as main or module, which for most packages would be a JS export. However, some packages do have other file extensions- see https://github.com/Decathlon/vitamin-web/blob/main/packages/sources/css/package.json#L21 for css. Bulma was the only instance of a sass main export I could find.

However, based on our conversation and discovery, I've reversed this and Sass will look relative to the package root instead of relative to the package main export.

proposal/package-importer.md Outdated Show resolved Hide resolved
Comment on lines 108 to 114
New step for [Loading a Source File], after "if argument is a relative URL"
step:

- If `argument` is a valid URL with scheme `pkg`:
- Let `resolved` be the result of resolving a pkg url
- If `resolved` is not null, let `argument` equal `resolved`, and continue.
Otherwise, return null.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two ways we could go here for defining "package importers":

  1. Reserve the URL scheme pkg: and dispatch it specially to a designated package importer, which is what this proposal does currently.
  2. Allow any importer to resolve pkg: imports and just provide an official recommendation for the structure of pkg: URLs as well as a built-in importer for Node.js semantics.

The benefits of option 1 are that you can give package importers some assistance in resolving URLs (as you do below), and that you can enforce more stringent requirements on them (like only processing pkg: URLs) than you can on general importers.

On the other hand, option 2 gives authors a lot more flexibility. For example, you can imagine someone wanting to support pkg: URLs in the browser via import maps, or even just from a virtual filesystem in web IDE. And authors who do want to target the filesystem can mitigate the pain by writing FileImporters that handle the pkg: URL scheme.

So my recommendation is this: Don't define any new language semantics. Instead, define the expectations for an importer that handles pkg: URLs: that the first component will be the package name, that it will automatically try to find an entrypoint file, that nested files can be addressed using /, and so on.

proposal/package-importer.md Outdated Show resolved Hide resolved
@jamesnw jamesnw requested a review from nex3 July 11, 2023 20:43
@jamesnw
Copy link
Author

jamesnw commented Jul 11, 2023

@nex3 I believe this second draft is ready for another review. I'm especially interested to hear if there are additional portions of the spec that I need to take into account and change. Thanks!

jamesnw and others added 3 commits July 12, 2023 09:03
* main:
  [Calculation API] Fix some issues brought up during implementation (sass#3631)
  Bump tj-actions/changed-files from 37.0.5 to 37.1.0 (sass#3632)
  [Calc Functions] Match the spec's behavior better for percentages (sass#3630)
  Bump tj-actions/changed-files from 37.0.2 to 37.0.5 (sass#3627)
  Fix a reference to a dead link (sass#3625)
proposal/package-importer.md Outdated Show resolved Hide resolved
proposal/package-importer.md Outdated Show resolved Hide resolved
js-api-doc/options.d.ts Outdated Show resolved Hide resolved
Comment on lines 334 to 335
* Whether or not to enable the built-in package importer to resolve any url
* with the `pkg` scheme.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be clearer that "the built-in package importer" specifically follows the Node.js resolution logic. When the time comes to add this to the documentation, we should probably either write out or link to documentation of exactly how it locates Sass files (that is, the "exports" field and so on).

proposal/package-importer.md Outdated Show resolved Hide resolved
proposal/package-importer.md Outdated Show resolved Hide resolved
proposal/package-importer.md Outdated Show resolved Hide resolved
proposal/package-importer.md Outdated Show resolved Hide resolved
proposal/package-importer.md Outdated Show resolved Hide resolved
proposal/package-importer.md Outdated Show resolved Hide resolved
proposal/package-importer.md Outdated Show resolved Hide resolved
proposal/package-importer.md Outdated Show resolved Hide resolved
proposal/package-importer.d.ts.md Show resolved Hide resolved

The new `usePkgImporter` option will not be available in the [Legacy JS API].
Third-party applications that don't support the modern API will be unable to use
the built-in package importer. Some notable examples follow.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had trouble getting into this last section without context that we're talking about Sass' legacy API. Hope this paragraph helps.

@jamesnw
Copy link
Author

jamesnw commented Jul 24, 2023

@nex3 I think this is ready for another round of review. One thing to consider is when you think it is ready enough to close this PR, and open a new PR over on the sass/sass Github. Thanks!

@jgerigmeyer jgerigmeyer requested a review from nex3 July 26, 2023 18:54
Copy link
Collaborator

@nex3 nex3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine to move this over to the public repo whenever you want. The official call for public comment happens between landing this PR and marking it as accepted anyway.

proposal/package-importer.d.ts.md Outdated Show resolved Hide resolved
proposal/package-importer.d.ts.md Outdated Show resolved Hide resolved

While the Dart Sass implementation allows for the use of the `package:` url
scheme, a similar standard doesn't exist in Node. We chose the `pkg:` url scheme
as it clearly communicates to both the user and compiler, and does not have
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clearly communicates what?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced with "We chose the pkg: url scheme as it clearly communicates to both the user and compiler that the specified files are from a dependency. The pkg: url scheme also does not have known conflicts in the ecosystem."

Comment on lines 159 to 160
[Parcel]:
https://github.com/parcel-bundler/parcel/blob/2d2400ded4615375ee6bd53ef77b4857ad1591dd/packages/transformers/sass/src/SassTransformer.js#L163
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit: We usually put even very long URL references on single lines.

Comment on lines 187 to 194
/**
* Whether or not to enable the built-in package importer to resolve any url
* with the `pkg` scheme. This importer follows Node.js resolution logic.
*
* @defaultValue `false`
* @category Input
*/
usePkgImporter?: boolean;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be clear in both the option name and documentation that this is the built-in Node.js package importer. It's entirely possible we'll want to add other built-in package importers in the future.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to useNodePkgImporter

proposal/package-importer.d.ts.md Outdated Show resolved Hide resolved
proposal/package-importer.d.ts.md Outdated Show resolved Hide resolved
proposal/package-importer.d.ts.md Outdated Show resolved Hide resolved
proposal/package-importer.d.ts.md Outdated Show resolved Hide resolved

The new `usePkgImporter` option will not be available in the [Legacy JS API].
Third-party applications that don't support the modern API will be unable to use
the built-in package importer. Some notable examples follow.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that so many existing plugins still don't support the modern API (:skull:), I wonder if we should support the Node.js package importer for the legacy API. It might not be so hard: we could just say that if usePkgImporter is set, pkg: loads go through the pkg: importer and if that returns null we invoke the legacy importer logic.

@jamesnw
Copy link
Author

jamesnw commented Aug 18, 2023

Moved to sass#3660. I think all conversation from this PR is resolved.

@jamesnw jamesnw closed this Aug 18, 2023
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

Successfully merging this pull request may close these issues.

4 participants