webpack file-loader does not load background image
Asked Answered
A

4

4

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.

Ahead answered 29/7, 2021 at 12:22 Comment(4)
It looks like it may be an issue with relative URL path of that background image. Can you change the image url to the absolute path and check if the background renders?Hector
I added the absolute path in my webpack file and import the image that way in my scss file but it still doesn't work. I experimented importing a random image that didn't exist in my assets folder and I got an error, therefore the path in itself works fine and the image I'm looking for gets called. I don't believe it's a path problem because of that, my theory is that the loader doesn't get that bakground image for some reason. But thanks for your suggestion anyway!Ahead
I have the same problem. Did you find a solution?Mccleary
No, I tried every version there was of the usage of both loaders on internet but none of them displayed the background image. I know the image gets called and the path is correct but for some reason the styles don't get applyAhead
A
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.

Ahead answered 5/8, 2021 at 16:57 Comment(0)
H
6

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.

Habitancy answered 4/10, 2021 at 1:7 Comment(0)
T
5

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/

enter image description here

Teresita answered 9/2, 2022 at 21:46 Comment(0)
A
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.

Ahead answered 5/8, 2021 at 16:57 Comment(0)
K
0

If you are building a NextJs application, You can move all the images or svg to your public folder and access them directly from there.

This worked for me

background-image: url("/pattern.png");
Kiser answered 27/3, 2023 at 14:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.