Define a standard for custom URL loaders
See original GitHub issueMany CSS features involve referring to assets outside the stylesheet using URLs: plain CSS @import
s, background images, and so on. It’s not always obvious how these assets will map to URLs on the server, though. Currently Sass provides no built-in support for this mapping, but doing so would be very useful.
I think Sass implementations should expose the ability for users to define their own URL-resolution logic that’s invoked for every url()
and every plain-CSS @import
. This should be done through a JS API that’s shared between Dart Sass and Node Sass, as well as a Dart API for Dart Sass users who invoke it via Dart.
I also think it would be valuable to provide some built-in resolution strategies that are available via the command line and through JS/Dart as standardized resolvers. For example, we might want to provide the ability to resolve URLs to data:
URLs that embed the document directly, or to map directories on the filesystem to URLs that will be served.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:15
- Comments:21 (5 by maintainers)
Top GitHub Comments
Whats the status? It kinda sucks to not be able to use ANY SCSS NPM PACKAGES (font packages, images etc.) because anytime I import/use them the relative urls won’t be rebased and go nowhere. I can’t fix this with something like
postcss-import
andpostcss-url
because they don’t know where the imported scss module came from, this can only be solved during scss compilation itself. Thank you so much to everyone whos investing their time in this!I met with some Sass team members to discuss this. We think it makes sense to define a new built-in function (which we’re tentatively calling
sass-url()
) that takes a string URL that refers to a file on disk and returns an unquotedurl()
string that refers to that file on the server.We think a new function is better than allowing every
url()
to be rewritten because many existing Sass files already containurl()
s that refer to files on the server in heterogeneous ways, which means our URL rewriting logic would somehow need to avoid breaking those existing references while also establishing a new convention for referring to local files. This is likely to be impossible, and even if it’s not, it’ll definitely involve a lot of migration churn that we’d just as soon avoid.How does
sass-url()
know which file a URL is referring to? We’ll add a new optional method to the custom importer API that returns the location of a resource referred to by a given URL, in the same way that importer returns Sass file contents. For almost all importers, this location should be afile:
URL referring to a physical file on disk. (Note that this means that this feature is blocked on #2509).The built-in filesystem importer that’s used to load the entrypoint and to load files from load paths will support this method, which will allow
sass-url()
to refer to files relative to the file that contains it and files from packages on the load path. If popular import plugins also implement this method, you’ll be able to writesass-url("~@foo/bar/asset.png")
as well.How does the browser find the files?
The location of the file returned by an importer (usually in the form of an absolute
file:
URL) will be passed to a URL rewriter plugin along with the location of the CSS file being generated (if that’s known). This plugin will be responsible for converting that URL to one that’s resolvable by browsers. This gives the downstream application maximal control over how its asset URLs are loaded.Sass will also provide a few built-in resolvers that should cover most common use-cases. One of these will load the contents of files from disk and inject them as
data:
URLs; this one will be enabled by default, since it’s the most foolproof method of ensuring the file contents makes it to the browser.