Unable to resolve absolute url () paths for background images in CSS using Webpack

I have the following Webpack configuration (roughly speaking, it has been simplified for this post):

const rootPublic = path.resolve('./public'); const LOCAL_IDENT_NAME = 'localIdentName=[name]_[local]_[hash:base64:5]'; const CSS_LOADER = `css?sourceMap&${LOCAL_IDENT_NAME}&root=${rootPublic}`; const SASS_LOADER = 'sass?sourceMap&includePaths[]=' + path.resolve(__dirname, './src/styles'); // ... loaders: loaders: [ { test: /\.(jpe?g|png|gif|svg)$/, loader: 'url-loader?limit=10000&name=[path][name].[ext]' }, { test: /\.scss$/, loader: config.DEVELOPMENT_MODE ? `style!${CSS_LOADER}!autoprefixer!${SASS_LOADER}` : ExtractTextPlugin.extract('style', `${CSS_LOADER}!autoprefixer!${SASS_LOADER}`) }, // ... ] 

Now this works fine for images that are usually referenced by scss files:

 .some-static-class { background: url('/images/bg.png'); } 

However, when using the :local directive :local it does not work:

 :local .SomeClass { background: url('/images/bg.png'); } 

And I think that since root defined for the CSS loader. I get a build error: Module not found: Error: Cannot resolve 'file' or 'directory' ./../../../../../../../../images/bg.gif

If instead I remove root from the css-loader configuration, then it builds fine, but then the path "looks" correct in the Chrome inspector, but when you really open the link in a new tab, it points to: chrome-devtools://devtools/bundled/"/images/bg.png" , which obviously does not resolve correctly.

I am not sure if the url-loader configuration problem or what exactly happens.

I played with various webpack configurations to specify resol.root, resolve.modulesDirectories, etc., but am completely not sure if they have any effect, or if I'm just wrong. I also met resolve-url-loader , but not sure if this is even what I need at all.

Any ideas? MTIA!

UPDATE

I should note that it works fine in Safari, but not in Chrome. So this seems like a bug specific to Chrome, but it is not practical to do all of our development in Safari.

I also stumbled upon vue-style-loader , which is a downloader style fork that claims to fix this problem, but fixes this by relying on a hacker -style outdated escape / unescape method.

+7
webpack webpack-dev-server
source share
2 answers

One possible solution that I could come up with was the following:

Use resolve-url-loader (right after sass-loader ):

 style!${CSS_LOADER}!autoprefixer!resolve-url!${SASS_LOADER} 

Then define static.alias for static images:

 resolve: { alias: { images: path.join(__dirname, 'public/images') } } 

And then in CSS you can point to images like this:

 :local .SomeClass { background: url('images/bg.png'); } 

Depending on your URL structure, you may also need to change the name url-loader param:

 { test: /\.(jpe?g|png|gif|svg)$/, loader: 'url-loader?limit=10000&name=images/[name].[ext]' } 

So I don’t know if there is a cleaner way to solve this problem, but this is the best that I could come up with so far. I would welcome any feedback or alternatives.

Thanks!

UPDATE 6/30/2016

There's a couple of PRs that will solve this problem, but the maintainer prefers the solution to be in CSS AST and not in the CSS loader ...

https://github.com/webpack/style-loader/pull/124 https://github.com/webpack/style-loader/pull/96

Here I hope that a real correction will happen soon ...

+5
source share

With webpack 2:

In your .scss files use ~ in front of the path.

 .yourClass { background: url('~img/wallpaper.png'); } 

Use the permission root from webpack, add it to your webpack.config.js:

 resolve: { modules: [ path.resolve(root), 'node_modules' ] }, 

It should work for @import too, for example @import "~ otherfile.scss"

+1
source share

All Articles