Security News
RubyGems.org Adds New Maintainer Role
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
resolve-url-loader
Advanced tools
Webpack loader that resolves relative paths in url() statements based on the original source file
The resolve-url-loader package is a webpack loader that resolves relative paths in url() statements based on the original source file. This is particularly useful when dealing with source maps and pre-processors like Sass, as it allows assets referenced in CSS to be correctly found and bundled by webpack.
Resolving relative URLs
This feature allows resolve-url-loader to adjust relative paths in url() statements so that they point to the correct location in a webpack build. The code sample shows how to include resolve-url-loader in a webpack configuration.
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'resolve-url-loader'
]
}
]
}
};
Source map support
resolve-url-loader can handle source maps, which is essential for debugging processed stylesheets like those written in Sass. The code sample demonstrates how to enable source map support in webpack loaders, including resolve-url-loader.
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: { sourceMap: true }
},
{
loader: 'resolve-url-loader',
options: { sourceMap: true }
},
{
loader: 'sass-loader',
options: { sourceMap: true }
}
]
}
]
}
};
file-loader resolves import/require() on a file into a url and emits the file into the output directory. It's similar to resolve-url-loader in that it helps with asset management, but it doesn't resolve relative URLs based on the original source file.
url-loader works like file-loader but can return a DataURL if the file is smaller than a byte limit. It's similar to resolve-url-loader as it deals with URLs in CSS and other files, but it doesn't specifically address the resolution of relative paths.
A webpack loader that rewrites relative paths in url() statements based on the original source file.
TL;DR Making Sass work with a feature based project structure
With webpack you can import a .scss
file (or some other compile-to-css file) and have a loader take care of the transpilation. With Sass (at least) this file can include a whole tree of source files into a single output.
We can imagine a virtual .css
file at the location the original .scss
import. Webpack expects any assets found in this CSS to be relative to the original imported file.
For projects with a feature based structure this will be a problem, since you will want to co-locate your assets with your .scss
partials.
Example - webpack imports index.scss
which includes feature foo
.
files | content |
---|---|
src / | |
index.scss | @import features/foo |
features / | |
_foo.scss | url(bar.png) |
bar.png |
Intuatively we want the assets in partial _foo.scss
relative to the partial, meaning url(bar.png)
.
However webpack's css-loader
will encounter url(bar.png)
and expect to find src/bar.png
. This is not the correct location and the build will fail.
Thankfully resolve-url-loader
provides the "url rewriting" that Sass is missing. Use it after the transpiler (such as sass-loader). It makes use of the source-map to find the original source file and rewrite url()
statements.
In our example it rewrites url(bar.png)
to url(features/bar.png)
as required.
Features
Use postcss
parser by default. This is long overdue as the old rework
parser doesn't cope with modern css.
Lots of automated tests running actual webpack builds. If you have an interesting use-case let me know.
Breaking Changes
join
option.root
option to be set.Migrating
Initially set option engine: 'rework'
for parity with your existing build. Once working you can remove this option or set engine: 'postcss'
explicitly.
Retain keepQuery
option if you are already using it.
The root
option now has a different meaning. Previously it limited file search. Now it is the base path for absolute or root-relative URIs, consistent with css-loader
. If you are already using it you can probably remove it.
If you build on Windows platform and your content contains absolute asset paths, then css-loader
could fail. The root
option here may fix the URIs before they get to css-loader
. Try to leave it unspecified, otherwise (windows only) set to empty string root: ''
.
via npm
npm install resolve-url-loader --save-dev
via yarn
yarn add resolve-url-loader --dev
The typical use case is resolve-url-loader
between sass-loader
and css-loader
.
:warning: IMPORTANT
resolve-url-loader
(regardless of devtool
).-loader
) otherwise you can get errors that are hard to debug.rules: [
{
test: /\.scss$/,
use: [
...
{
loader: 'css-loader',
options: {...}
}, {
loader: 'resolve-url-loader',
options: {...}
}, {
loader: 'sass-loader',
options: {
sourceMap: true,
sourceMapContents: false
}
}
]
},
...
]
Refer to test
directory for full webpack configurations (as used in automated tests).
option | type | default | description | |
---|---|---|---|---|
engine | 'rework' 'postcss' | 'postcss' | The css parser engine. | |
sourceMap | boolean | false | Generate a source-map. | |
keepQuery | boolean | false | Keep query-string and/or hash suffixes. e.g. url('./MyFont.eot?#iefix') Be aware downstream loaders may remove query-string or hash. | |
debug | boolean | false | Display debug information. | |
silent | boolean | false | Do not display warnings. | |
root | string | unset | Similar to the (now defunct) option in css-loader .This string, possibly empty, is prepended to absolute URIs. Absolute URIs are only processed if this option is set. | |
join | function | inbuilt | advanced | Custom join function. Use custom javascript to fix asset paths on a per-case basis. Refer to the default implementation for more information. |
absolute | boolean | false | useless | Forces URIs to be output as absolute file paths. This is retained for historical compatibility but is likely to be removed in the future, so let me know if you use it. |
A rework or postcss process is run on incoming CSS.
Each url()
statement may imply an asset or may not. Generally only relative URIs are considered. However if root
is specified then absolute or root-relative URIs are considered.
For each URI considered, the incomming source-map is consulted to determine the original file where the url()
was specified. This becomes the base
argument to the join
function, whose default implementation is something like the following pseudocode.
join(uri, base?) =>
compose(path.normalize, path.join)(base || options.join, uri);
Note that for absolute uri
then the base
is absent. In the default implementation the root
option is used instead.
Full file search has been discontinued in version 3, however it is possible to specify a custom join
function.
There is the added complexity that base
may be an iterator. However resolve-url-loader
exports some useful functions that makes a custom join
easier.
Following join
the URI has become an absolute path. Back-slashes are then converted to forward-slashes and the path is made relative to the initial resource being considered.
Use the debug
option to see verbose information from the join
function.
Where url()
statements are created in a mixin the source file may then be the mixin file, and not the file calling the mixin. Obviously this is not the desired behaviour.
Ensure this is indeed the problem as there are many ways to misconfigure webpack. Try inlining the mixin and check that everything works correctly. However ultimately you will need to work around this.
Tested macOS
and Windows
for node 6.x
.
All webpack1
-webpack4
with contemporaneous loaders/plugins.
Refer to test
directory for full webpack configurations (as used in automated tests).
The engine:postcss
is by far the more reliable option.
The engine:rework
option is retained for historical compatibility but is likely to be removed in the future, so let me know if you use it.
If you need production css source-map it is best to avoid the combination webpack4
with engine:rework
. Tests show a systematic flaw in the outgoing source-map mappings.
By "absolute URIs" we more correctly mean assets with root-relative URLs or absolute file paths.
Absolute paths are not processed by default
These are not processed unless a root
is specified.
However recall that any paths that are processed will have windows back-slash converted to posix forward-slash. This can be useful since some webpack loaders can choke on windows paths. By using root: ''
then resolve-url-loader
effectively does nothing to absolute paths except change the back-slash.
It can also be useful to process absolute URIs if you have a custom join
function and want to process all paths. However this is perhaps better done with some separate postcss
plugin.
Webpack is difficult to configure but extremely rewarding.
Remove this loader and make sure it is not a problem with a different loader in your config (most often the case)
I am happy for you to raise an issue to ask a question regarding this package. However ensure you follow the check-list first.
Currently I am not dogfooding this loader in my own work. I may rely on you being able to isolate the problem in a simple example project and to help debug.
I am happy this loader helps so many people. Open-source is provided as-is so please try not project your frustrations. There are some really great people who follow this project who can help.
Before raising a new issue:
I am happy to take pull requests, however:
FAQs
Webpack loader that resolves relative paths in url() statements based on the original source file
We found that resolve-url-loader demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.
Security News
Research
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.