webpack file-loader does not load background image

All we need is an easy explanation of the problem, so here it is.

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.

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

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.

Method 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.

https://webpack.js.org/guides/asset-modules/

webpack file-loader does not load background image

Method 3

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.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply