Skip to content

Webpack can’t resolve @import of scss/css

I have a main Stylesheet style.scss, which I imported in my main JavaScript file script.js:

import "./style.scss";

This works great, and I could build my website that way in dev mode. Now I wanted to try and use separate Stylesheet and import them in my main stylesheet with the @import rule, like so:

@import "./blocks/SCSS/test.scss" screen and (min-width: 600px);

But now I get this error message:

ERROR in ./dev/style.scss (./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./dev/style.scss)  
Module build failed (from ./node_modules/css-loader/dist/cjs.js):  
Error: Can't resolve './blocks/SCSS/test.scss' in 'D:Art FilesDesignEigene ProjekteWP Book Theme Devdev'

And I don’t understand why it can’t resolve it. I use modules for my JavaScript as well, which works great. But now with SCSS, it does not work at all.

I tried googling for a solution and checked out several open threads, none could help me.
Here are some I checked out on Stackoverflow:

My Node version was 12.18.3, where I had the error first. Now I updated my node to the LTS to 14.15.4, still the same error.

Here are my Webpack config files:

// webpack.common.js

const path = require("path");

module.exports = {
  entry: "./dev/script.js",
  
  module: {
    rules: [
      {
        test: /.html$/i,
        use: ["html-loader"],
      },
      {
        test: /.(svg|png|jpg)$/i,
        use: {
          loader: "file-loader",
          options: {
            esModule: false,
            name: "[name].[hash].[ext]",
            outputPath: "assets/images",
          },
        },
      },
    ],
  },
};


// webpack.dev.js

const path = require("path");
const common = require("./webpack.common.js");
const { merge } = require("webpack-merge");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = merge(common, {
  mode: "development",
  plugins: [
    new HtmlWebpackPlugin({
      template: "./dev/post.html",
    }),
  ],
  module: {
    rules: [
      {
        test: /.scss$/i,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
    ],
  },
  devServer: {
    contentBase: "./dist",
  },
  output: {
    filename: "script.dev.js",
    path: path.resolve(__dirname, "dist"),
    publicPath: "./",
  },
});

Here are my webpack dependencies:

"devDependencies": {
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^5.0.1",
    "file-loader": "^6.2.0",
    "html-loader": "^1.3.2",
    "html-webpack-plugin": "^4.5.0",
    "mini-css-extract-plugin": "^1.3.3",
    "optimize-css-assets-webpack-plugin": "^5.0.4",
    "sass": "^1.32.0",
    "sass-loader": "^10.1.0",
    "style-loader": "^2.0.0",
    "terser-webpack-plugin": "^5.0.3",
    "webpack": "^5.11.1",
    "webpack-cli": "^4.3.0",
    "webpack-dev-server": "^3.11.1",
    "webpack-merge": "^5.7.3"
  },

Answer

This is what I did to fix my problem. Amaresh already mentioned something, about what I might be missing, but that didn’t help me out with my problem, as I was given no real explanation on why that would help.
In the end, I did install sass*, and since node-sass is deprecated, I didn’t pay any mind to it.

The way I used @import was probably wrong. I was trying to do it the native CSS way (MDN), but SCSS might have been overwriting that. @import by SCSS is also deprecated by now and not recommended. When I rechecked the SCSS Website, I went to their guide on how to use SCSS, and they mentioned how I could use @use to import another stylesheet. What I learned was that I need to use Partials. I had to lead filenames with an underscore to create a namespace for that, and import it using the @use rule.

From their example:

// _base.scss
$font-stack:    Helvetica, sans-serif;
$primary-color: #333;

body {
  font: 100% $font-stack;
  color: $primary-color;
}
// styles.scss
@use 'base';

.inverse {
  background-color: base.$primary-color;
  color: white;
}

* I don’t know if the installation of sass actually helped or not. Since the package is dealing with JavaScript, which I have not done so in my file. But since the package is also mentioned in the sass-loader, I will keep it.

What is important to remember when using @use is how you handle the file in the new file.

// src/_list.scss
@mixin list{
    ul {
        display: flex;
        flex-direction: row;
        li {
            text-align: center;
            padding: 5px;
        }
    }
}

By only calling the URL, you have to specify the namespace and then what you want to use from that namespace.

// styles.scss
@use "src/list";

header {
  @include list.list;
}

You can call a new namespace and give it a custom name.

// styles.scss
@use "src/list" as myList;

header {
  @include myList.list;
}

Or you can call it and name it with an asterisk, making it available, without having to write the namespace when calling it.

// styles.scss
@use "src/list" as *;

header {
  @include list;
}

For further reading, please check out their documentation on @use.