Reputation: 2809
I am using webpack and simply trying to apply a background-image
specified in a url
property to an html element.
I've looked at several threads (this one for instance) but did not find something that works for me.
Here's my setup :
// index.js
import React from 'react'
import styles from './styles.css'
const MyComponent = () => {
return (
<div className={styles.container}></div>
)
}
export default MyComponent
// styles.css
.container {
background-image: url('../../../static/public/images/my-background.jpg');
}
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: path.join(__dirname, "src", "index.js"),
output: {
path: path.join(__dirname, "dist"),
filename: "index.bundle.js"
},
mode: process.env.NODE_ENV || 'development',
resolve: {
modules: [path.resolve(__dirname, "src"), "node_modules"],
},
devServer: {
static: path.join(__dirname, 'src')
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, "src", "index.html"),
}),
new CopyWebpackPlugin({
patterns: [
{
from: 'static',
to: 'static'
}
]
})
],
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ["babel-loader"]
},
{
test: /\.(css)$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(jpg|png|svg|gif)$/,
use: ['url-loader', 'file-loader'],
},
],
},
}
When reaching localhost I do see the path being resolved :
However, when I try to reach that url, all I see is a little white square ...
This is definitely not the image. I do find the image present in my build in ./dist/static/public/images/my-background.jpg
Note that the image has a large size : 3842 × 2162
I think this has to do with webpack loader configuration, but did not quite find how to adjust it to get it to work here. Any help would be very appreciated !
Upvotes: 12
Views: 18215
Reputation: 6486
I had just upgraded from webpack v4 to v5 and, as per the webpack docs on asset management for images, I had to make sure the images in the css files were actually currently located where I was saying they were and not where they will be.
So, changing from:
...
background: url(/static/images/header.jpg)
...
to:
...
background: url(/images/header.jpg)
...
everywhere fixed this issue for me.
Upvotes: 1
Reputation: 53
The solution (using a webpack version prior to 5.0) is to turn off css-loader
's URL parsing, because the CSS file isn't updating the URL string when webpack builds
module.exports = {
...
module: {
rules: [
{ //https://webpack.js.org/loaders/css-loader/
test: /\.css$/,
use: ["style-loader"]
},
{ //https://webpack.js.org/loaders/css-loader/
test: /\.css$/,
loader: "css-loader",
options: {
url: false,
}
}
]
}
}
Note that this will make so that the files used in .css will not be hashed and will be structured like the original /public/ folder upon building the project to the /dist/ folder. Which is what makes it work.
For reference see this github issue and this one
Also, I'm using:
Update: Having a rule object that uses 'url-loader' might override out files from the other rules. So, in that case you should remove it and have the options in the 'css-loader' like so:
{
test: /\.css$/,
loader: "css-loader",
options: {
url: true,
esModule: false
}
}
Try commenting out each option and rules and see the results to check what each option and rule is doing. Delete the .dist/ folder before each build (because it's not automatically clean after each build) to make sure you know what files are produced and when.
Upvotes: 1
Reputation: 15670
I had the same issue and it finally worked by using ~
to reference the project directory and access public
folder from there.
background-image: url("~/public/images/person.png");
And this is working fine for me :)
OR And the other alternative would be to move your images to the src
directory, webpack will pack them in a folder called static/media
as static files
Upvotes: 4
Reputation: 3043
You are may be using a new version of Webpack, where url-loader
and file-loader
are deprecated and Asset Modules
are the alternatives.
Try using:
{
test: /\.(jpg|png|svg|gif)$/,
type: 'asset/resource',
},
instead.
For more information click here.
Upvotes: 14