sass-loader: Doesn't work by default with yarn v2 / berry

Actual Behavior / Situation

The new version of Yarn, v2, packs dependencies in .zip files instead of keeping them in node_modules. sass-loader uses node-sass which is a native binary and it bypasses the module resolution of yarn, resulting in errors such as:

ERROR in ./src/styles/app.scss (./.yarn/$$virtual/css-loader-virtual-25ac65d05c/0/cache/css-loader-npm-3.4.2-300ee159b3-1.zip/node_modules/css-loader/dist/cjs.js?sourceMap=true!./.yarn/$$virtual/sass-loader-virtual-528b2c3b95/0/cache/sass-loader-npm-8.0.2-f0d209ad64-1.zip/node_modules/sass-loader/dist/cjs.js!./src/styles/app.scss)
Module build failed (from ./.yarn/$$virtual/sass-loader-virtual-528b2c3b95/0/cache/sass-loader-npm-8.0.2-f0d209ad64-1.zip/node_modules/sass-loader/dist/cjs.js):
SassError: File to import not found or unreadable: .yarn/$$virtual/bootstrap-virtual-a4283f726d/0/cache/bootstrap-npm-4.4.1-16b3a7c0d2-1.zip/node_modules/bootstrap/scss/bootstrap-reboot.scss.
        on line 1 of /src/styles/app.scss
>> @import '~bootstrap/scss/bootstrap-reboot';

Notice how the path of the file is shown as .../.yarn/$$virtual/bootstrap-virtual-a4283f726d/0/cache/bootstrap-npm-4.4.1-16b3a7c0d2-1.zip/node_modules/bootstrap/scss/bootstrap-reboot.scss. (there’s a .zip file in the middle)

Modification Proposal

The only way this can work right now is by setting the implementation option to sass instead of node-sass. Since sass is a javascript implementation, it will be able to resolve files from the .zip files through yarn’s pnp resolution mechanism.

The alternative is to run commands like yarn unplug bootstrap, so that files are stored unzipped in the yarn cache.

I think it would be a good idea to detect if yarn v2 is being used and show a better error message than the one above. I feel this is going to start becoming a common problem.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 22
  • Comments: 33 (12 by maintainers)

Most upvoted comments

Thanks everyone for this thread. I lost a couple of hours on this.

React

The problem lies with react-scripts. Anyone experiencing this bug in react (using create-react-app) try following this:

  1. upgrade react-scripts, this will probably solve your issue: yarn add react-scripts.

If #1 was insufficient try the following:

  1. yarn add sass sass-loader --dev
  2. You can get rid of node-sass: yarn remove node-sass
  3. edit .yarnrc.yml (seems to fix without this step):
packageExtensions:
  ...
  react-scripts@*:
    dependencies:
      "sass-loader": "*" 
    peerDependencies:
      "sass": "*" 

I went with sass instead of node-sass for the time being and worked fine.

I understand the urgency on something being a stopper @kubijo but it was straight forward. All I had to do was to add in package.json the 3rd party css libraries along with "sass": "^1.26.3" & change in webpack config the sass loader in module.rules to the following:

            {
              loader: require.resolve('sass-loader'),
              options: {
                implementation: require('sass'),
              }
            }

To get sass-loader to play nicely with yarn 2, I had to add this to my .yarnrc.yml

# .yarnrc.yml
packageExtensions:
  'sass-loader@*':
    optionalDependencies:
      node-sass: '*'

~Does the concept of optionalDependencies exist in regular package.jsons?~

edit: Looks like this package marks node-sass as an optional peer dependency(?). Not sure why yarn 2 doesn’t like that.

edit II: @soloalex1 I believe we were running into the same issue. I was still experiencing it in yarn(?)@2.0.0-rc.29

Same here.

@import '../../css/mixins/keyframes.scss';
^
      File to import not found or unreadable: ~/.yarn/$$virtual/shared-virtual-723db036ba/1/shared/ui/css/mixins/keyframes.scss.

any update on this?

@rtritto your problem has nothing to do with either Yarn nor Webpack. As the error hints, your third-party (video.js) hardcodes node_modules in the sass files they ship, which cannot work when installs are made without node_modules (which has been the default starting from 2.0).

https://cdn.jsdelivr.net/npm/video.js@7.11.8/src/css/video-js.scss

We switch on sass (dart) by default (you can still use node-sass) in the next version, so there should be no more problems, I will update the documentation for yarn pnp users, I think it is enough, don’t know how we can improve error message in this case, because for importer any value in @import/@use is URL, in theory we can check .yarn directory in resolved path, but I don’t think we really need extra check here, maybe node-sass improve yarn PnP support in future, anyway if somebody have ideas how to improve it better feel free to send more information to docs.

I’ll make a note to re-visit this later on and will try to create both working and broken examples… now I just need to finish-up the migration so that the rest of my team can use it.

I’d like to finish that today.

@soloalex1 That’s not related to sass loader though. Try the yarn discord if you’re stuck. You can get clues there.