Next.js does not resolve SCSS that is imported by my dependencies:
styles/home.module.scss uses @material/elevation (this works fine).@material/elevation uses @material/animation (this fails).Steps to reproduce the behavior, please provide code snippets or a repository:
$ git clone https://github.com/nicholaschiang/with-sass
$ cd with-sass/
$ yarn
$ yarn dev
You'll notice that when you run yarn dev the Next.js server starts up properly
but the sass-loader is unable to resolve my dependency's imports.
It seems to import the @material/elevation package just fine:
// styles/home.module.scss
@use '@material/elevation
But it doesn't seem to be able to import @material/animation for the
@material/elevation package:
error - ./styles/home.module.scss (./.yarn/$$virtual/css-loader-virtual-393ee7c517/0/cache/css-loader-npm-3.5.3-0f886851e6-910936f0ac.zip/node_modules/css-loader/dist/cjs.js??ref--5-oneOf-3-1!./.yarn/$$virtual/next-virtual-4df8b3b97e/0/cache/next-npm-9.5.1-e14f31e6e9-effa9056b8.zip/node_modules/next/dist/compiled/postcss-loader??__nextjs_postcss!./.yarn/cache/resolve-url-loader-npm-3.1.1-cf1a268137-7b113ac9e6.zip/node_modules/resolve-url-loader??ref--5-oneOf-3-3!./.yarn/$$virtual/sass-loader-virtual-dbafe3ebab/0/cache/sass-loader-npm-8.0.2-f0d209ad64-e23d9b308f.zip/node_modules/sass-loader/dist/cjs.js??ref--5-oneOf-3-4!./styles/home.module.scss)
SassError: Can't find stylesheet to import.
â•·
23 │ @use "@material/animation/variables";
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
╵
.yarn/cache/@material-elevation-npm-7.0.0-aaa8862010-5ea26d080e.zip/node_modules/@material/elevation/_variables.scss 23:1 @forward
.yarn/cache/@material-elevation-npm-7.0.0-aaa8862010-5ea26d080e.zip/node_modules/@material/elevation/_index.scss 1:1 @use
/home/nchiang/repos/with-sass/styles/home.module.scss 1:1 root stylesheet
I've had this error before when using Next.js with
MWC but was
able to fix it by specifying an includePaths configuration in next.config.js
like so:
// next.config.js
const path = require('path');
module.exports = {
sassOptions: {
includePaths: [
path.resolve(__dirname, 'node_modules'),
],
},
};
Now, I'm not sure how to tell sass-loader to use Yarn PNP's module resolution.
Next.js should be able to resolve the Yarn PNP modules.
Seems like #6049 was closed rather prematurely.
Perhaps this could be fixed by using a custom importer: https://github.com/sass/node-sass#importer--v200---experimental
The issue is that sass-loader tries to load ./@material/animation/_variables.scss from @material/elevation/_variables.scss which doesn't work.
The relative path is produced here in 9.0.0 https://github.com/webpack-contrib/sass-loader/blob/c6d56e48728eb8d65258e6ee7606507187e0b457/src/utils.js#L223 and here in 8.0.2 https://github.com/webpack-contrib/sass-loader/blob/03773152760434a2dd845008c504a09c0eb3fd91/src/importsToResolve.js#L24
So it tries to look for these
[
'./@material/animation/_variables.scss',
'./@material/animation/_variables.sass',
'./@material/animation/_variables.css',
'./@material/animation/variables.scss',
'./@material/animation/variables.sass',
'./@material/animation/variables.css',
'./@material/animation/variables',
'@material/animation/variables'
]
from C:\with-sass\.yarn\cache\@material-elevation-npm-7.0.0-aaa8862010-5ea26d080e.zip\node_modules\@material\elevation
@evilebottnawi is the module import @material/animation/variables supposed to become relative?
It seems as if the issue originates from loader-utils assuming that @material/animation/variables is a relative URL:
const url = "@material/animation/variables";
const request = loaderUtils.urlToRequest(url); // "./@material/animation/variables"
This is not the case. So either MWC changes all of their imports to prepend a ~ (which I don't think they'll do), or loader-utils has to stop assuming that all paths are by default relative (and instead assume that all paths are by default modules unless ./ is preprended).
Please do not use Yarn v2 PnP with webpack@4, only webpack@5 support PnP, also my strong recommendation - do not use includePaths and PNP, it is compatibility, because sass do not use require.resolve for @import and can't load virtual files :smile:
You can try https://github.com/arcanis/pnp-webpack-plugin, but I don't know real compatibility
@merceyz and yes and not https://github.com/webpack-contrib/sass-loader/blob/c6d56e48728eb8d65258e6ee7606507187e0b457/src/utils.js#L234, contains ['./@material/animation/variables', '@material/animation/variables'], because you can have a directory with @ character in name
@evilebottnawi I switched to Webpack v5 and I got the same error.
@evilebottnawi The PnP plugin is already installed, the import @material/animation/variables causes sass-loader to try to load this list:
[
'./@material/animation/_variables.scss',
'./@material/animation/_variables.sass',
'./@material/animation/_variables.css',
'./@material/animation/variables.scss',
'./@material/animation/variables.sass',
'./@material/animation/variables.css',
'./@material/animation/variables',
'@material/animation/variables'
]
Would it make sense to also try these?
'@material/animation/_variables.scss',
'@material/animation/_variables.sass',
'@material/animation/_variables.css',
'@material/animation/variables.scss',
'@material/animation/variables.sass',
'@material/animation/variables.css',
Or is this behavior expected and therefor it's an issue with how @material/elevation/_variables.scss declares its import and @material/animation/variables should be changed to @material/animation/_variables.scss?
@merceyz that suggestion looks great! According to the Sass lang spec, the @material/animation/variables is definitely the correct way to import that partial (plus, that MWC package is maintained by Google, so I'm pretty sure they got their stuff right haha).
@nicholaschiang Are you sure what you uses latest version? Where you got list?
Anyway adding @material/animation/_variables make sense, anyway we need reproducible test repo with error? Can you open a new issue with minimum reproducible test repo with error?
@evilebottnawi there's already a repro linked in the original issue description (it's the default Next.js template with a SCSS import added).
And I was using Webpack 5.0.0-beta.22 originally (I can add it to the repro if you want too) by specifying Yarn resolutions (as per the instructions in #13341) when I first encountered this issue.
Thanks, I will look at this in near future
Just note - next.js uses sass-loader@8, but latest is sass-loader@9
Confirmed, it is bug, reproduced with sass-loader@9, WIP
Resolution in sass is terrible :disappointed:
Fixed, ETA is tomorrow, I found other strange resolution bug (very rare case), anyway you need to update sass-loader to latest, it will not work with sass-loader@8