webpackcss-loaderwebpack-file-loader

Webpack: resolve url in CSS properly using css-loader and file-loader


I have a webpack project where I need to set the background in css through url(). In other places I would want to import images and use them in my JS code so I use file-loader. My webpack.config rules look like so (note that I don't use SASS):

module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  },
  module: {
    rules: [
      {
        test: /\.(m|c)?jsx?$/i,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
          },
        },
      },
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
          },
        ]
      },
      {
        test: /\.(png|jpe?g|gif)$/i,
        use: {
          loader: 'file-loader',
          options: {
            esModule: false
          }
        }
      },
      {
        test: /\.svg$/i,
        use: {
          loader: 'file-loader',
        }
      },
      {
        test: /\.pug$/i,
        use: {
          loader: 'pug-loader',
          options: {
            pretty: true
          }
        }
      }
    ],
  }
}

My problem is that file-loader messes with css-loader when resolving urls so instead of just emitting an image into the output folder I get two files: a text file with the following structure (webpack module):

module.exports = __webpack_public_path__ + "78c74331dbce5633ed0e385397a47eac.jpg";

And the image file proper: 78c74331dbce5633ed0e385397a47eac.jpg. Resulted CSS points to this webpack module in the above instead of the image itself. How do I prevent webpack from creating this module and make it utilize the path to the image? When I remove file-loader everything works fine, but I need file-loader to load images in other places of my app.

My CSS rule looks like so:

.image {
  width: 200px;
  height: 200px;
  background-image: url("../../assets/pizza.jpg");
}

My folder structure:

./src
  /css
    /index.css
  /index.js
./assets
  /pizza.jpg

Solution

  • I was able to solve this problem by adding the following option to css-loader:

    {
      loader: 'css-loader',
      options: {
        esModule: false
      }
    }