Webpack + file-loader + sass-loader is having trouble resolving relative paths for CSS background images.
The compiled SCSS file contains a path to the background image that is relative to /dist/
instead of relative to the SCSS/CSS document. I researched this problem; sass-loader recommends using resolve-url-loader (with source maps). However, adding the resolve-url-loader made no difference to the compiled CSS.
I have been able to resolve the issue by setting the 'publicPath' to '../..' on the file-loader. Or by disabling the 'url' setting on the css-loader. Neither is a good solution and causes issues with copying files and referencing images via HTML or other sources.
The online examples of Webpack and CSS place the CSS and images in the same folder (often in the root). This is not an optimal choice for my webpack implementation. The concept of structuring files in subfolders seems like a fairly basic requirement. Is this simply the wrong approach?
Running Webpack ^3.5.1. Sass-loader ^6.0.6. File-loader ^0.11.2. Css-loader ^0.28.4.
File structure
example/
├── dist/
│ ├── assets
│ │ ├── media
│ │ │ └── logo.png
│ │ └── styles
│ │ ├── app.css
│ │ └── app.css.map
│ ├── index.html
│ └── app.bundle.js
└── src/
├── assets
│ ├── media
│ │ └── logo.png
│ └── styles
│ └── app.scss
└── app.js
app.scss
body {
background: url(../media/logo.png);
}
app.css
body {
background: url(assets/media/logo.png); //This should be ../media/logo.png
}
app.js
require('./assets/styles/app.scss');
webpack.config.js
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './src/app.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.bundle.js'
},
devtool: 'source-map',
module: {
loaders: [
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
sourceMap: true
}
}, {
loader: 'resolve-url-loader'
}, {
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
})
}, {
test: /\.png$/,
use: [
{
loader: 'file-loader',
options: {
name: 'assets/media/[name].[ext]'
}
}
]
}
]
},
plugins: [
new ExtractTextPlugin({
filename: 'assets/styles/app.css'
})
]
}
To be able to use CSS in your webpack app, you need to set up a new loader. Out-of-the-box, webpack only understands Javascript and JSON. With a loader, you can translate another type of file to a format that webpack understands and can work with. There are many webpack loaders and each loader has a specific purpose.
By default, Webpack will inline your CSS as Javascript tags that injects the CSS into the page. This sounds strange but it lets you do hot reloading in development. In production you extract them to a file using the ExtractTextPlugin, and require it with a normal link tag.
css-loader is the npm module that would help webpack to collect CSS from all the css files referenced in your application and put it into a string. And then style-loader would take the output string generated by the above css-loader and put it inside the <style> tags in the index. html file.
sass-loader is a loader for Webpack for compiling SCSS/Sass files. style-loader injects our styles into our DOM. css-loader interprets @import and @url() and resolves them. mini-css-extract-plugin extracts our CSS out of the JavaScript bundle into a separate file, essential for production builds.
ExtractTextPlugin
has a publicPath
option that can resolve this issue.
{
test: /\.scss$/,
include: [
path.resolve(__dirname, "src/assets/styles")
],
use: ExtractTextPlugin.extract({
publicPath: '../../',
use: [
{
loader: 'css-loader',
options: {
sourceMap: true
}
}, {
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
})
}
Added include
array to target files in a particular directory. Recommended for instances where all stylesheets are located in the same folder.
The reason why path in url(...)
is incorrect is webpack generate path relative to output dir, not the output css file.
You can use css-url-relative-plugin to solve this problem, it will replace url(...)
with correct relative path by re-calculate relationship of output css and assets file.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With