-
Notifications
You must be signed in to change notification settings - Fork 47
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
Added Yarn PnP support #83
Conversation
…'t like sass's done function
Ok, it's finally all working. You can now import a file in the following ways:
My importer has a specific case to handle local files. If an import begins with Finally, thanks to @merceyz for the tip about letting Yarn PnP know what is actually requesting the file, this patch doesn't require |
Ok, final code is done. Per the sass spec, url imports must start with |
I also added some comments, so everyone can see what and why the code is doing what it does. |
Can confirm, url imports are working as intended. As far as I can tell, everything is good and the green light can be given. Unless anyone can think of an edge case I may have missed. |
index.ts
Outdated
// Have Node resolve the path to the file we're requesting. | ||
// When using a plain node_modules project, this works as | ||
// expected. When using Yarn PnP, Yarn will unplug the package, | ||
// and give the path to the file. Unplugging a file simply | ||
// means unzipping it since most packages aren't equipped to | ||
// work with zip archives directly. Also, the 'paths' option | ||
// tells Yarn what file is requesting this file, so PnP | ||
// integrity remains intact. For Node, paths serves as an | ||
// additional set of paths to look for the import in. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yarn doesn't unplug on demand, it's done on install if required due to native files, postinstalls, or when explicitly requested.
All packages that use the fs
module can work with zip files as PnP patches it to support reading from them.
For Node, paths serves as an additional set of paths to look for the import in
For both PnP and Node it's to tell it where the resolution should start, so it's not "additional"
https://nodejs.org/dist/latest-v16.x/docs/api/modules.html#modules_require_resolve_request_options
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough, that was a misunderstanding on my part. PnP is such a massive departure from what I'm used to that I am still coming to grips with it (not that that's a bad thing, this kinda needed to happen for a while). As for the fs
module support is that due to Yarn patching it, or is that just native node?
Also, with regards to the resolution, that was really just overly technical documentation. The way it is phrased makes it sound as if it's adding new resolution paths, but I'll update the comment. Thanks for clearing that up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this phrasing capture a bit more accurately what's going on?
// Have Node resolve the path to the file we're requesting.
// When using a plain node_modules project, this works as
// expected. When using Yarn PnP, Yarn will resolve an absolute
// path to the file and the sass compiler will access that file
// directly from the zip archive it's contained in. The 'paths'
// option simply tells Node and Yarn where resolution should
// start (i.e. who is requesting this file).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean technically, both Node and Yarn PnP are doing the same thing, so it's a bit misleading. They're both just getting the absolute path to a file. It's just in the case of Node, it's the runtime doing it and with Yarn PnP (and, as I've recently found out, pnpm), it's the package manager doing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternative verbiage, I'll let you decide which is more accurate and concise.
// Have Node or PnP resolve a path to the file we're
// requesting. In the case of a standard node_modules project
// Node will handle the resolution. For a PnP project, the
// package manager will handle the resolution. Both will
// return an absolute path to the file, which will be passed to
// the sass compiler, so it can get the file in question.
//
// If a file cannot be located, this will generate an error.
I also don't specifically mention Yarn, since it isn't the only PnP based package manager.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the late response, the way you ended up wording it looks great
As for the fs module support is that due to Yarn patching it, or is that just native node?
The PnP implementation patches it
https://github.com/yarnpkg/berry/blob/d2e592a74e1de6fcf9e2e97a5d9712cf7eba159c/packages/yarnpkg-pnp/sources/loader/_entryPoint.ts#L26-L37
index.ts
Outdated
// Finally, return the resolved file...if we can confirm it | ||
// exists. If not, you guessed it...abort, and let sass handle | ||
// the import | ||
return existsSync(resolved) ? { file: resolved } : null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
require.resolve
will throw if it can't find it so this should always be true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not so sure about that one. In my testing, when it couldn't find a file, it just assumed it was relative to the root of the plugin package. It never threw an exception, nor did Yarn (though I know Yarn patches this API for PnP). For example say I was looking for the file ./components/Header/header', if it wasn't able to resolve the path, it just assumed the path was
{PROJECT_ROOT}/.yarn/cache/rollup-plugin-scss-https-ab37d281de-9cbfba33c6.zip/node_modules/rollup-plugin-scss/components/Header/header.scss'. Maybe that's a bug, or maybe it's intended behavior for relative imports, I'm not 100% certain on how the resolution works at the low level.
Correction, it is intended behavior. Turns out, the package resolve-patch
does just that. If the path begins with a relative character, it just does an fs.resolve()
and assume the path exists. Fair enough, since I've added in all the checks, you are correct, this shouldn't be needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given what I now know (sorry, by the way, I'm not very familiar with the internals of Node or Yarn), do you think it's safe to just do return { file: resolved }
? I mean, I passed local files and urls off to sass, and since require.resolve()
should throw an error if a file can't be resolved, there's literally no reason the code would get that far if a file wasn't located.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that should be fine
I updated the code comments to be a bit more accurate now that I have a better understanding of all of this. I also surrounded the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, is it possible to add an automated test for this behaviour?
In connection with issue #60, this pull request adds Yarn PnP support by allowing Yarn to provide any of the necessary files from NPM. All local files are still simply passed directly to the sass compiler of the user's choice.