'webpack file-loader does not load background image
I've been having this problem for a while and I see that other people have it too, but even though I have the same code as them it is still not working and I don't know what I'm doing wrong. I'm working with react, webpack, babel and scss for a project. At first I create a main component which has a background image tha loaded without problems, but when I added a carousel component I had an error that said that I needed a loader for the images to appear (html images, not bakground). So I looked it up on the internet and two loaders appeared: url-loader and file-loader, I installed both and added one in my webpack config file as it was said in the documentation. The images loaded, but the background image of the main component didn't, and not only that, all the styles for the background didn't apply either.
This is my webpack config file, I tried putting both loaders, then only one, then the other, but none of them worked. I tried every solution tha came across stackoverflow but the code isn't working and there is no errors in my terminal.
///////EDIT
I added absolute paht but it's still not working. The image gets fetched because I'd get an error if it isn't so I don't think this is a path issue. I updated the webpack config file
const HtmlWebPackPlugin = require("html-webpack-plugin");
const path = require("path");
const htmlPlugin = new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
});
module.exports = {
mode: "development",
resolve: {
alias: {
Assets: path.resolve(__dirname, 'src/assets/')
}
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.s?css$/,
use: ["style-loader", "css-loader", "sass-loader"]
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
esModule: false
},
},
]
}
]},
plugins: [htmlPlugin],
devServer:{
historyApiFallback : true
}
}
And this is my main component and its scss file (where the bakground image lies)
React component
import React from "react";
import { NavBar } from "../components/NavBar";
import CarouselComponent from "../components/Carousel";
export const MainPage = () => {
return (
<div>
<NavBar />
<div>
<div className="main">
<h1>Find a new musical to watch!</h1>
<a className="main__btn" href="/musicals">See categories</a>
</div>
<div className="login-info">
<h2 className= "login-info__login">See our forum for reacomendations and post your own!</h2>
<div className="login-info__btn-login-position">
<a className="btn login-btn-position-config" href="#"><strong>Loging</strong></a>
</div>
<span></span>
<h2 className= "login-info__create-account">Don't have an account? Create one!</h2>
<div className="login-info__btn-create-position">
< a className="btn login-btn-position-config" href="#"><strong>Create account</strong></a>
</div>
</div>
<CarouselComponent />
</div>
</div>
)
}
Scss component
body{
padding: 56px 50px 0 50px;
background-color: $color-background;
}
.main{
font-family: $primary-title-font;
height: 90%;
background: url(Assets/main_background.jpg) no-repeat center center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
h1{
background-image: linear-gradient(90deg, rgba(1,50,1,1) 5%, rgba(70,82,25,1) 51%, rgba(78,82,29,1) 87%);
background-size: 100%;
background-clip: text;
-webkit-background-clip: text;
-moz-background-clip: text;
-webkit-text-fill-color: transparent;
-moz-text-fill-color: transparent;
position: absolute;
top: 15rem;
left: 5rem;
font-size: 5rem;
}
&__btn{
position: absolute;
top: 350px;
left: 459px;
border-radius: 10% / 20%;
padding: 1rem;
text-decoration: none;
color: $primary-black-color;
background: $golden-button;
font-size: 1.5rem;
&:hover{
color: $primary-black-color;
}
&:active{
transform: translateY(2px);
}
}
}
And this is the carousel component with its scss
React component
import React, { Component } from "react";
import "react-responsive-carousel/lib/styles/carousel.min.css";
import { Carousel } from 'react-responsive-carousel';
import hamilton from "../assets/hamilton.jpg";
import six from "../assets/six_the_musical.jpg";
import hadestown from "../assets/hadestown.jpg";
import theGuy from "../assets/the_guy_who_didnt_like_musicals.png";
class CarouselComponent extends Component {
render (){
return (
<Carousel autoPlay = {true} infiniteLoop={true} interval={4000} showStatus={false} useKeyboardArrows={true} showThumbs={false}>
<div className="carousel__box-1">
<img src={hamilton} alt="Hamilton wallpaper"/>
</div>
<div className="carousel__box-2">
<img src={six} alt="Six wallpaper"/>
</div>
<div className="carousel__box-3">
<img src={hadestown} alt="Hadestown wallpaper"/>
</div>
<div className="carousel__box-4">
<img src={theGuy} alt="The guy who didnt like musicals wallpaper"/>
</div>
</Carousel>
)
}
}
export default CarouselComponent;
Scss component
.carousel__box{
height: 9rem;
img{
min-width: 100%;
min-height: 100%;
}
}
I'll also add my folder structure in case it's necessary
/project
/dist
/node_modules
/src
/assets
(all the images are stored here)
/components
card.js
cardBlock.js
carousel.js
navbar.js
/pages
main.js
musicals.js
notFound.js
/sass
(all scss are stored here, there is a styles.scss that imports the rest of files and it's
called in index.js)
index.html
index.js (imports all react component an renders them in index.html)
.babelrc
packaje.json
packaje-lock.json
webpack.config.js
////// NEW EDIT
I found that if you put esModule: false
inside the url-loader options the image gets loaded.
Solution 1:[1]
Adding esModule: false
inside the url-loader options the image helped me, though I'm not sure why, if someone has the same issue you should try this trick.
Solution 2:[2]
if you have webpack 5 then don't install (file-loader, url-loader, raw-loader) they come with 5. Everything will work, just include the image in the css file as you would without webpack.
Solution 3:[3]
This is what worked for me https://webpack.js.org/guides/asset-management/. You need to have css-loader
already set. This is not using file-loader
or url-loader
, so beware of the implications, but it's a simple solution recommended by Webpack. I removed the settings for the file-loader
and updated with:
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
The explanation is this:
When using the css-loader, as shown above, a similar process will occur for url('./my-image.png') within your CSS. The loader will recognize this is a local file, and replace the './my-image.png'
This worked perfectly for me, so hope it helps.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | alexgarciaalcuadrado |
Solution 2 | Peter Csala |
Solution 3 | leandro lavore |