parcel: @parcel/transformer-sass: Fails to resolve path to node module

šŸ› bug report

In the newly released parcel 2.0.0-beta.2 (and nightly builds before that) transformer-sass can’t resolve paths to installed node modules.

The error looks similar to https://github.com/parcel-bundler/parcel/issues/5813 but happens on build and serve.

šŸŽ› Configuration (.babelrc, package.json, cli command)

package.json

"dependencies": {
    "autoprefixer": "~10.2.5",
    "core-js": "~3.9.1",
    "foundation-sites": "6.6.3",
    "husky": "~5.1.3",
    "jquery": "~3.6.0",
    "motion-ui": "~2.0.3",
    "parcel": "2.0.0-beta.2",
    "postcss": "~8.2.7",
    "sass": "~1.32.8",
  },
  // automatically added by parcel:
  "devDependencies": {
    "@babel/core": "^7.13.10",
    "@parcel/transformer-sass": "2.0.0-beta.2"
  }

.scssrc

{
  "includePaths": ["node_modules"]
}

In my scss files, I’m importing scss files from foundation-sites, e.g.

@import "foundation-sites/scss/global";

šŸ¤” Expected Behavior

I expect the scss file to be included (used to still work with parcel 2.0.0-beta.1).

😯 Current Behavior

yarn parcel serve and yarn parcel build throw an error. No css file is build.

Build failed.
@parcel/transformer-sass: Got unexpected null
   ā•·
19 │ @import "foundation-sites/scss/global";
   │         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   ╵
  scss/main.scss 19:9  root stylesheet
Error: Got unexpected null
   ā•·
19 │ @import "foundation-sites/scss/global";
   │         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   ╵
  scss/main.scss 19:9  root stylesheet
    at Object._newRenderError (/var/code/themes/mo-foundation-base/node_modules/sass/sass.dart.js:13537:19)
    at Object._wrapException (/var/code/themes/mo-foundation-base/node_modules/sass/sass.dart.js:13374:16)
    at _render_closure1.call$2 (/var/code/themes/mo-foundation-base/node_modules/sass/sass.dart.js:80373:21)
    at _RootZone.runBinary$3$3 (/var/code/themes/mo-foundation-base/node_modules/sass/sass.dart.js:27269:18)
    at _FutureListener.handleError$1 (/var/code/themes/mo-foundation-base/node_modules/sass/sass.dart.js:25797:19)
    at _Future__propagateToListeners_handleError.call$0 (/var/code/themes/mo-foundation-base/node_modules/sass/sass.dart.js:26094:49)
    at Object._Future__propagateToListeners (/var/code/themes/mo-foundation-base/node_modules/sass/sass.dart.js:4543:77)
    at _Future._completeError$2 (/var/code/themes/mo-foundation-base/node_modules/sass/sass.dart.js:25927:9)
    at _AsyncAwaitCompleter.completeError$2 (/var/code/themes/mo-foundation-base/node_modules/sass/sass.dart.js:25270:12)
    at Object._asyncRethrow (/var/code/themes/mo-foundation-base/node_modules/sass/sass.dart.js:4292:17)

On previous tries the error message was ā€œFailed to resolveā€ with an identical stack trace.

šŸ’ Possible Solution

Maybe scss files need to be imported differently now?

šŸ”¦ Context

The issue makes any recent version of parcel 2 unusable for us. We need to be able to import scss files from other node modules.

šŸ’» Code Sample

šŸŒ Your Environment

Software Version(s)
Parcel 2.0.0-beta.2
Node 12.19.0
npm/Yarn yarn 1.22.5
Operating System Ubuntu 20.10

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 22 (2 by maintainers)

Commits related to this issue

Most upvoted comments

I had the same import error with

@import 'bootstrap/scss/functions', 'bootstrap/scss/variables';

But it appears I was able to specify the filename directly to get it working:

@import 'bootstrap/scss/_functions.scss', 'bootstrap/scss/_variables.scss';

I’m having the exact same problem. Only I’m using Material as a CSS framework and when I import a SCSS file from Material, it imports several other files.

So even when I specify the exact file name, it still gives an error because there is no way for me to fix the internal imports of the framework

I had the same import error with

@import 'bootstrap/scss/functions', 'bootstrap/scss/variables';

But it appears I was able to specify the filename directly to get it working:

@import 'bootstrap/scss/_functions.scss', 'bootstrap/scss/_variables.scss';

This is still having issues, and I’ve identified why: basically, Parcel’s custom implementation of the path resolution (resolvePathImporter) is still quite broken.

@jteppinette, if you dive into you node_modules/@parcel/transformer-sass/lib/SassTransformer.js and comment out lines 131-136, I would bet your Sass compiles correctly (we’re doing the exact same thing as you above).

Here are the issues I fixed before I gave up:

  • I started by just diving into the resolve to see what it was trying to resolve. First, I found that the resolver is looking for files without the extensions (which is supported by the sass resolver and is also how Bootstrap chooses to do imports). In other words, it’s looking for node_modules/bootstrap/scss/functions rather than node_modules/bootstrap/scss/functions.scss. If you just manually add the .scss extension to the filepath (e.g. const filePath = _path().default.resolve(p, u) + ".scss";), things start resolving.
  • The next problem is that certain elements are still not resolving because of bad path joining. For instance, the resolver tried to resolve this path to a file (replaced project root with [PROJECT_ROOT]): [PROJECT_ROOT]file%3A[PROJECT_ROOT]/node_modules/bootstrap/scss/functions.scss. The URLs are preprocessed before they are passed to this resolver (see the returned function of the resolver, specifically const url = rawUrl.replace(/^file:\/\//, '');). However, I don’t think all of these bad patterns are being removed exhaustively. I don’t know enough about the Parcel internal engine to capture them all, but for the sake of demonstration, I added a custom rule to remove file%3A from the prev argument so that these paths would resolve correctly.
  • For me, the two above changes make almost all of the files resolve correctly, which is great. However, it appears that I hit another snag somewhere else because I got a slightly different error showing that Parcel tried to resolve a path similar to the one above and failed:
    Error: ENOENT: no such file or directory, open '/[PROJECT_ROOT]file%3A[PROJECT_ROOT]/node_modules/bootstrap/scss/_accordion.scss'
    

At this point, I gave up because it’s clear the resolver needs a major rework (IMO).

@DeMoorJasper and @devongovett, I’d be happy to put together a PR to work around this, but I just honestly don’t know enough about the Parcel engine to do a true fix justice. Would you be open to me adding a key in the .sassrc file that allows you to bypass Parcel’s resolver and use the native Sass resolver until this is fixed? This would be easy to implement and, while those that bypass Parcel’s resolver can’t expect to benefit from caching, I’d argue that’s much better than just having to switch away from Parcel v2 altogether.

@DeMoorJasper @devongovett

This is still failing on ^2.0.0-rc.0.

I am having the same issue as @silash35. Bootstrap’s relative imports are failing:

@parcel/transformer-sass: Can't find stylesheet to import.
    @import "functions";
    file:node_modules/bootstrap/scss/bootstrap.scss

IMHO this is still a very relevant issue and I do not understand why it was closed.

Have you tried @import 'npm:normalize.css/normalize; https://parceljs.org/languages/css/#%40import ?

@jgentes thanks for the hint! So at least there’s some kind of workaround.

However, that’s not how SASS is supposed to work: https://sass-lang.com/documentation/at-rules/import#finding-the-file https://sass-lang.com/documentation/at-rules/import#partials

I had the same import error with

@import 'bootstrap/scss/functions', 'bootstrap/scss/variables';

But it appears I was able to specify the filename directly to get it working:

@import 'bootstrap/scss/_functions.scss', 'bootstrap/scss/_variables.scss';

That fixes it for me temporarily, but breaks the watcher when importing SCSS from another monorepo workspace. Basically every SCSS file behind a namespace is static and therefore not watched.

Update (2021-03-29): I got a similar error compared to #6039. If you have a .sassrc inside a workspace this will be regarded as root for Sass, and therefor won’t listen to any upper changes. Basic rule: Always have all your .*rc and *.lock files in the project root, otherwise you’ll feel stupid a few days later.

Ensure you have it in your .babelrc file:

{
  "presets": ["@babel/preset-env"]
}

Otherwise I would recommend Stack Overflow for something like this. Only submit an issue if you are pretty certain it is a bug 😃