Search code examples
webpacksasssass-loader

Webpack CSS Loader Error: "Unknown word" on variables


Whenever I try to run npm build on my code, I experience many errors along the lines of the following:

asset main.js 901 KiB [emitted] (name: main) 1 related asset
asset icon.png 795 bytes [compared for emit] [from: src/styles/icon.png] (auxiliary name: main)
orphan modules 51.1 KiB (javascript) 975 bytes (runtime) [orphan] 17 modules
runtime modules 2.15 KiB 7 modules
javascript modules 710 KiB
  modules by path ./ 452 KiB
    modules by path ./src/ 449 KiB 54 modules
    ./index.js 3.26 KiB [built] [code generated]
    ./index.scss 39 bytes [built] [code generated] [1 error]
  modules by path ../ 258 KiB
    modules by path ../../common/temp/node_modules/.pnpm/@[email protected]/node_modules/@...(truncated) 22.4 KiB 31 modules
    modules by path ../cursor-effects/ 13.2 KiB 5 modules
    modules by path ../../backend/ 155 KiB
      ../../backend/common/dist/main.js 134 KiB [built] [code generated]
      ../../backend/event-emitter/dist/main.js 20.9 KiB [built] [code generated]
    + 7 modules
./src/styles/icon.png 42 bytes (javascript) 795 bytes (asset) [built] [code generated]

ERROR in ./src/styles/_iconview.scss (../../common/temp/node_modules/.pnpm/[email protected][email protected]/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].use[1]!./src/styles/_iconview.scss)  
Module build failed (from ../../common/temp/node_modules/.pnpm/[email protected][email protected]/node_modules/css-loader/dist/cjs.js):

SyntaxError

(95:7) client\src\styles\_iconview.scss Unknown word

  93 |                  overflow: visible;
  94 |
> 95 |                  #{ $self }__icon {
     |                     ^
  96 |                          background-color: rgb(0 0 200 / 90%);
  97 |                  }
 @ ./index.scss.webpack[javascript/auto]!=!../../common/temp/node_modules/.pnpm/[email protected][email protected]/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].use[1]!../../common/temp/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[1].use[2]!./index.scss 11:0-214 20:26-59
 @ ./index.scss
 @ ./index.js 32:0-22

I have the following Webpack configuration for the project:

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

const mode = process.env.NODE_ENV || "development";
const minimize = mode === "production";
const plugins = [];

if (mode === "production") {
    plugins.push(new CssMinimizerPlugin());
}

module.exports = {
    mode,
    devtool: "source-map",
    entry: [path.resolve(__dirname, "index.js")],
    output: {
        library: "MyClientName",
        libraryTarget: "umd",
        umdNamedDefine: true,
        sourceMapFilename: "[file].map",
        filename: "[name].js",
    },
    optimization: {
        minimize,
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: "[name].css",
            chunkFilename: "[id].css",
        }),
        ...plugins,
    ],
    module: {
        rules: [
            {
                test: /\.(svg|png|jpe?g|gif|webp)$/,
                type: "asset/resource",
                exclude: /node_modules/,
                generator: {
                    filename: "[name][ext]",
                },
            },
            {
                test: /\.(sa|sc|c)ss$/,
                exclude: /node_modules/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: "css-loader",
                        options: {
                            sourceMap: true,
                        },
                    },
                    {
                        loader: "sass-loader",
                        options: {
                            sourceMap: true,
                        },
                    },
                ],
            },
            {
                test: /\.html$/i,
                loader: "html-loader",
            },
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader",
                },
            },
        ],
    },
};

The code is valid SCSS and worked for me before, but I recently updated my dependency versions and this issue sprung up. Why am I encountering this problem, and how can I resolve it so the SCSS is parsed and compiled properly?


Solution

  • The problem turned out to be how the modules were imported in index.scss. When I use the traditional method, it works:

    @import "./src/styles/variables";
    @import "./src/styles/core";
    @import "./src/styles/window";
    @import "./src/styles/notifications";
    @import "./src/styles/login";
    @import "./src/styles/loading";
    @import "./src/styles/search";
    @import "./src/styles/iconview";
    

    But the reason the code had changed was because stylelint --fix complained and automatically updated the code to the following:

    @import url("./src/styles/variables");
    @import url("./src/styles/core");
    @import url("./src/styles/window");
    @import url("./src/styles/notifications");
    @import url("./src/styles/login");
    @import url("./src/styles/loading");
    @import url("./src/styles/search");
    @import url("./src/styles/iconview");
    

    And with that syntax, npm run build gives the following errors, because the file path is different (i.e. ./src/styles/_iconview.scss):

    ERROR in ./index.scss
    Module build failed (from ../../common/temp/node_modules/.pnpm/[email protected][email protected]/node_modules/css-loader/dist/cjs.js):
    Error: Can't resolve './src/styles/variables' in 'frontend\client'
    

    So I had changed the file paths to be correct to appease stylelint, like so:

    @import url("./src/styles/_variables.scss");
    @import url("./src/styles/_core.scss");
    @import url("./src/styles/_window.scss");
    @import url("./src/styles/_notifications.scss");
    @import url("./src/styles/_login.scss");
    @import url("./src/styles/_loading.scss");
    @import url("./src/styles/_search.scss");
    @import url("./src/styles/_iconview.scss");
    

    And that was when Webpack started giving all these errors. I was able to find a compromise by disabling stylelint surrounding the imports:

    /* stylelint-disable */
    @import "./src/styles/variables";
    @import "./src/styles/core";
    @import "./src/styles/window";
    @import "./src/styles/notifications";
    @import "./src/styles/login";
    @import "./src/styles/loading";
    @import "./src/styles/search";
    @import "./src/styles/iconview";
    /* stylelint-enable */
    

    This results in stylelint still running as expected within the imported SCSS files, resolving all the issues. I believe the issue stems from the combination of url() and @import, because the code is processed by css-loader twice, with once before the Sass has been transformed.