Gerald Wichmann
Gerald Wichmann

Reputation: 457

Can't resolve '/images/bg.jpg' after updating css-loader to v4

css-loader was at 3.5.3 and my app worked fine. updated it and only it to 4.3.0, and now i get the below compilation error. i'm having trouble figuring out why when looking through the "breaking changes" inherent with an upgrade to v4.

Possibly something to do with my use of a url in a .scss file where the only reference to /images/bg.jpg exists? I have a styles.scss file which imports a "_box-layout.scss" file wherein lies:

.box-layout {
  align-items: center;
  background: url('/images/bg.jpg');
  background-size: cover;
  display: flex;
  height: 100vh;
  justify-content: center;
  width: 100vw;
}

The compilation error:

ERROR in ./src/styles/styles.scss
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/css-loader/dist/cjs.js):
Error: Can't resolve '/images/bg.jpg' in 'C:\Users\gwich\dev\javascript\react\rental-props\src\styles'
    at C:\Users\gwich\dev\javascript\react\rental-props\node_modules\enhanced-resolve\lib\Resolver.js:209:21
    at C:\Users\gwich\dev\javascript\react\rental-props\node_modules\enhanced-resolve\lib\Resolver.js:285:5
    at eval (eval at create (C:\Users\gwich\dev\javascript\react\rental-props\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:13:1)
    at C:\Users\gwich\dev\javascript\react\rental-props\node_modules\enhanced-resolve\lib\UnsafeCachePlugin.js:44:7
    at C:\Users\gwich\dev\javascript\react\rental-props\node_modules\enhanced-resolve\lib\Resolver.js:285:5
    at eval (eval at create (C:\Users\gwich\dev\javascript\react\rental-props\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:13:1)
    at C:\Users\gwich\dev\javascript\react\rental-props\node_modules\enhanced-resolve\lib\Resolver.js:285:5
    at eval (eval at create (C:\Users\gwich\dev\javascript\react\rental-props\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:25:1)
    at C:\Users\gwich\dev\javascript\react\rental-props\node_modules\enhanced-resolve\lib\DescriptionFilePlugin.js:67:43
    at C:\Users\gwich\dev\javascript\react\rental-props\node_modules\enhanced-resolve\lib\Resolver.js:285:5
    at C:\Users\gwich\dev\javascript\react\rental-props\node_modules\webpack\lib\NormalModule.js:316:20
    at C:\Users\gwich\dev\javascript\react\rental-props\node_modules\loader-runner\lib\LoaderRunner.js:367:11
    at C:\Users\gwich\dev\javascript\react\rental-props\node_modules\loader-runner\lib\LoaderRunner.js:233:18
    at context.callback (C:\Users\gwich\dev\javascript\react\rental-props\node_modules\loader-runner\lib\LoaderRunner.js:111:13)
    at Object.loader (C:\Users\gwich\dev\javascript\react\rental-props\node_modules\css-loader\dist\index.js:154:5)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
 @ ./src/app.js 13:0-30
 @ multi babel-polyfill ./src/app.js

My webpack config if interesting:

const path = require("path");
const webpack = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

process.env.NODE_ENV = process.env.NODE_ENV || "development";

if (process.env.NODE_ENV === "test") {
  require("dotenv").config({ path: ".env.test" });
} else if (process.env.NODE_ENV === "development") {
  require("dotenv").config({ path: ".env.development" });
}

module.exports = (env) => {
  const isProduction = env === "production";

  return {
    entry: ["babel-polyfill", "./src/app.js"],
    output: {
      path: path.join(__dirname, "public", "dist"),
      filename: "[name].js",
    },
    optimization: {
      splitChunks: {
        cacheGroups: {
          commons: {
            test: /[\\/]node_modules[\\/]/,
            name: 'vendors',
            chunks: 'initial',
          },
        },
      },
    },
    mode: isProduction ? 'production' : 'development',
    module: {
      rules: [
        {
          loader: "babel-loader",
          test: /\.js$/,
          exclude: /node_modules/,
        },
        {
          test: /\.less$/,
            use: [
              {
                loader: MiniCssExtractPlugin.loader,
                options: {
                  sourceMap: !isProduction,
                },
              },
              {
                loader: "css-loader",
                options: {
                  sourceMap: !isProduction,
                },
              },
              {
                loader: "less-loader",
                options: {
                  sourceMap: !isProduction,
                  modifyVars: {
                    "primary-color": "#1c88bf",
                    "link-color": "#1c88bf",
                    "border-radius-base": "2px",
                  },
                  javascriptEnabled: true,
                },
              }
            ],
        },
        {
          test: /\.s?css$/,
          use: [
            {
              loader: MiniCssExtractPlugin.loader,
              options: {
                sourceMap: !isProduction,
              },
            },
            {
              loader: "css-loader",
              options: {
                sourceMap: !isProduction,
              },
            },
            {
              loader: "sass-loader",
              options: {
                sourceMap: !isProduction,
              },
            },
          ],
        },
        {
          test: /\.(svg|eot|ttf|woff|woff2)$/,
          use: {
            loader: "file-loader",
            options: {
              name: "[name].[ext]",
              outputPath: "fonts/",
            },
          },
        },
      ],
    },
    plugins: [
      // new BundleAnalyzerPlugin(),
      new MiniCssExtractPlugin({ filename: '[name].css'}),
      new webpack.DefinePlugin({
        "process.env.FIREBASE_API_KEY": JSON.stringify(process.env.FIREBASE_API_KEY),
        "process.env.FIREBASE_AUTH_DOMAIN": JSON.stringify(process.env.FIREBASE_AUTH_DOMAIN),
        "process.env.FIREBASE_DATABASE_URL": JSON.stringify(process.env.FIREBASE_DATABASE_URL),
        "process.env.FIREBASE_PROJECT_ID": JSON.stringify(process.env.FIREBASE_PROJECT_ID),
        "process.env.FIREBASE_STORAGE_BUCKET": JSON.stringify(process.env.FIREBASE_STORAGE_BUCKET),
        "process.env.FIREBASE_MESSAGING_SENDER_ID": JSON.stringify(process.env.FIREBASE_MESSAGING_SENDER_ID),
      }),
    ],
    devtool: isProduction ? "source-map" : "inline-source-map",
    devServer: {
      contentBase: path.join(__dirname, "public"),
      historyApiFallback: true,
      publicPath: "/dist/",
    },
  };
};

Upvotes: 3

Views: 6295

Answers (2)

Lauri Harpf
Lauri Harpf

Reputation: 1488

Faced the same issue after updating from css-loader 3.6.0 to 5.2.7. Resolved it by disabling css-loader from parsing url paths by changing webpack config from

{
    loader: "css-loader",
},

to

{
    loader: "css-loader",
    options: {
        url: false
    }
},

As discussed at https://github.com/webpack-contrib/css-loader#url, this defaults to true.

Allow to enable/disables handling the CSS functions url and image-set. If set to false, css-loader will not parse any paths specified in url or image-set. A function can also be passed to control this behavior dynamically based on the path to the asset. Starting with version 4.0.0, absolute paths are parsed based on the server root.

Upvotes: 1

Gerald Wichmann
Gerald Wichmann

Reputation: 457

I managed to solve this problem thanks to this article.

First, I installed url-loader

npm install url-loader --save-dev

Next, I updated the path in the background url in my webpack.config.js file in the rules section (the image was located in /public/images/bg.jpg while my _box-layout.scss file was in /src/styles/components/ imported by /src/styles/styles.scss):

  rules: [
    {
      test: /\.(png|jpg)$/,
      loader: 'url-loader'
    },

Lastly, I updated my _box-layout.scss file:

.box-layout {
  align-items: center;
  background: url('../../public/images/bg.jpg');
  background-size: cover;
  display: flex;
  height: 100vh;
  justify-content: center;
  width: 100vw;
}

Upvotes: 1

Related Questions