css-loader: Cannot @import "bar.scss" when the extension is not .css (4.0.0 regression)

css-loader ≥ 4.0.0 gives Error: Can't resolve 'bar.scss' when I try to @import "bar.scss". It works when the extension is .css but not when it’s .scss. I bisected this to commit edf5347e4203a62e50b87248a83da198afdc6eba (#1099). The problem is triggered by the restrictions: [/\.css$/i] setting that was hard-coded here:

https://github.com/webpack-contrib/css-loader/blob/edf5347e4203a62e50b87248a83da198afdc6eba/src/index.js#L50-L56

  • Operating System: NixOS 20.09
  • Node Version: 14.7.0
  • NPM Version: 6.14.7
  • webpack Version: 4.44.1
  • css-loader Version: 4.2.1

Expected Behavior

With css-loader 3.6.0:

$ npx webpack
Hash: 18aeb4131231a0da692b
Version: webpack 4.44.1
Time: 122ms
Built at: 08/12/2020 4:28:49 PM
  Asset      Size  Chunks             Chunk Names
main.js  8.05 KiB    main  [emitted]  main
Entrypoint main = main.js
[./foo.scss] 396 bytes {main} [built]
[./node_modules/css-loader/dist/cjs.js!./bar.scss] 278 bytes {main} [built]
    + 1 hidden module
Done in 0.46s.

Actual Behavior

With css-loader ≥ 4.0.0:

$ npx webpack 
Hash: 8a377e383c6ebf971c58
Version: webpack 4.44.1
Time: 120ms
Built at: 08/12/2020 4:30:02 PM
  Asset      Size  Chunks             Chunk Names
main.js  6.36 KiB    main  [emitted]  main
Entrypoint main = main.js
[./foo.scss] 2.58 KiB {main} [built] [failed] [1 error]

ERROR in ./foo.scss
Module build failed (from ./node_modules/css-loader/dist/cjs.js):
Error: Can't resolve 'bar.scss' in '/tmp/b'
    at /tmp/b/node_modules/enhanced-resolve/lib/Resolver.js:209:21
    at /tmp/b/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/tmp/b/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:13:1)
    at /tmp/b/node_modules/enhanced-resolve/lib/UnsafeCachePlugin.js:44:7
    at /tmp/b/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/tmp/b/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:13:1)
    at /tmp/b/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/tmp/b/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:25:1)
    at /tmp/b/node_modules/enhanced-resolve/lib/DescriptionFilePlugin.js:67:43
    at /tmp/b/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/tmp/b/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:26:1)
    at /tmp/b/node_modules/enhanced-resolve/lib/ModuleKindPlugin.js:30:40
    at /tmp/b/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/tmp/b/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:13:1)
    at /tmp/b/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/tmp/b/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:13:1)
    at /tmp/b/node_modules/enhanced-resolve/lib/forEachBail.js:30:14
    at /tmp/b/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/tmp/b/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:13:1)
    at /tmp/b/node_modules/enhanced-resolve/lib/UnsafeCachePlugin.js:44:7
    at /tmp/b/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/tmp/b/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:13:1)
    at /tmp/b/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/tmp/b/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:25:1)
    at /tmp/b/node_modules/enhanced-resolve/lib/DescriptionFilePlugin.js:67:43
    at /tmp/b/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/tmp/b/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:14:1)
    at /tmp/b/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/tmp/b/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:25:1)
    at /tmp/b/node_modules/enhanced-resolve/lib/DescriptionFilePlugin.js:67:43

Code

// webpack.config.js
module.exports = {
  mode: "development",
  entry: "./foo.scss",
  module: {
    rules: [{ test: /\.s?css$/, use: "css-loader" }],
  },
};
/* foo.scss */
@import "bar.scss"
/* bar.scss */
html {
  background: red;
}

How Do We Reproduce?

Create the three files above and run npm i webpack webpack-cli css-loader; npx webpack.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 17 (11 by maintainers)

Commits related to this issue

Most upvoted comments

I still don’t understand how an example with exactly one @import can possibly be mixing CSS and SCSS @imports. With css-loader 3 or with #1165, foo.scss and bar.scss are processed in exactly the same way.

Because @import should load only CSS, I asked you to test it in the browser, but you ignored me

If what you’re saying is that no @import should ever be allowed to make its way to css-loader unless it refers directly to a CSS file that requires no further processing, then what is supposed to be the point of importLoaders?

No, you can still use postcss-loader and other loaders.

Please create reproducible test repo

Again ignore me.

parser: "postcss-scss", only parser file as SCSS it is not compile it, so I can’t understand what variables are you talking about

I don’t see any documentation suggesting that postcss-scss is unsafe? I understand that it does not, by itself, provide all the features of Sass, but that doesn’t make it unsafe.

plugins: [ // not important for this self-contained example ],

Most of plugins for postcss designed for pure CSS, not for sass/scss, so I as written above postcss-scss should not be used here, it is for other dev tools, for example - stylelint uses it for parsing scss and linting, prettier for formatting.

I don’t think we should document it here.

I explained above why I don’t want to use sass-loader.

You can create an own loader, if you have non standard approaches.

Sorry it is limitation, if you want to use sass/scss you need to use sass-loader.