sass-loader: SassError: Can't find stylesheet to import when it contains @forward with _index file
- Operating System: Mac OS
- Node Version: v10.16.3
- NPM Version: v6.13.4
- webpack Version: v4.41.5
- sass-loader Version: v8.0.2
- dart-sass version: v1.25.0
Expected Behavior
Expected sass-loader to resolve the module when _index.scss files are used.
Actual Behavior
sass-loader throws following error when @import’ed Sass file contain @forward statement with _index file. (See reproducible steps below).
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
SassError: Can't find stylesheet to import.
Code
See complete example here: https://github.com/abhiomkar/sass-module-bug
How Do We Reproduce?
git clone git@github.com:abhiomkar/sass-module-bug.git
cd sass-module-bug
npm i
npx webpack
Notice the error:
[./fixture-import.scss] 434 bytes {main} [built] [failed] [1 error]
ERROR in ./fixture-import.scss
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
SassError: Can't find stylesheet to import.
╷
1 │ @forward "@material/base" as mdc-base-*;
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
╵
node_modules/@material/button/_mixins.import.scss 1:1 @import
/Users/abhiomkar/code/sass-bug-module/fixture-import.scss 1:9
Changing webpack entry file fixture-import.scss => fixture-use.scss would fix the error.
UPDATE: See this comment for temporary workaround.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 29
- Comments: 63 (45 by maintainers)
Commits related to this issue
- docs: Documentation and examples for v5.0 (#2041) - Add usage for MDC Sass modules to getting started guide - Add density mixin examples - Switch `highlight.js` theme to `scss/github` - Temporary ... — committed to trimox/angular-mdc-web by trimox 4 years ago
- Update Node packages to latest; fix Webpack config; implement new SCSS format Includes a workaround for Webpack not loading @use declarations correctly: https://github.com/webpack-contrib/sass-loader... — committed to mbestavros/mbestavros.github.io by mbestavros 4 years ago
- Remove node-sass and add temporary workaround for sass-loader. - Source1 (remove node-sass): https://github.com/material-components/material-components-web/issues/5502#issuecomment-586061492 - Source... — committed to esso23/MatBlazor by esso23 4 years ago
- Update packages -------------------------- The sass-loader package v9 has important bug fixes for issues described at https://github.com/webpack-contrib/sass-loader/issues/804 — committed to marcolabreu/vue-material-adapter by marcolabreu 4 years ago
- Force upgrade sass-loader dependency to version 9 Fixes SassError: Can't find stylesheet to import. @import "@material/base/mixins"; @see https://github.com/webpack-contrib/sass-loader/issues/804 — committed to AXeL-dev/anime-tracker by AXeL-dev 3 years ago
I did some investigation to see how the URLs are resolved. I’m not very familiar with how webpack importer works but seems like resolve() function in webpackImporter is resolving the url to
index.jsinstead ofindex.scssor_index.scssfile. (@trimox spotted this in his comment earlier about presence of index.js causing import failures).Workaround for now is to disable
webpackImporteroption insass-loader:@evilebottnawi Hope this helps debug the issue 😃
I will work on that fix tomorrow
And please stop saying that there are bugs everywhere except your code, we are both developers and may make a mistake in our code, so I prefer to investigate firstly and then say where the problem is. Thanks
Anyway I found solutions, try to shipped it tomorrow
Starting working on “@import”/“@forward”/“@use” problems, sorry for the slight delay, covid 😞 approximate ETA is the end of the next week.
It will be major release:
file.import.extIn theory it should not break nothing, but in very very very some rare cases it can be broken due our invalid logic, so I prefer release that as a major release
I feel like things are getting a little antagonistic, so I want to take a step back and apologize for my part in that. I’m not trying to make your life difficult or blame you for stuff breaking, and it was definitely not very cool of me to list off behavioral issues in your code that you were already aware of.
I do hear you when you say that using the solution I propose will break other users, and when I push back on that it’s not that I think you’re wrong so much as that one of two things is true: I’m wrong, or I haven’t explained myself very clearly (or a combination of both as it seems is the case here). In either case I want to understand more details about exactly why it won’t work so I can either fix my suggestion or explain better.
I think both of us ultimately want to find a solution that works well for all Sass users and is as future-proof as possible. I’m sorry it’s taking so long to land on one, but I’m confident that if we work together we can get there.
From your
@import "file"example, I’m thinking that I didn’t explain myself well. I was going to try to explain myself better with code in hand, but I tested the reproduction again against the latest version of this package and it looks like you already fixed the issue in aeb86f078d01460990aa8b06fce81b6fe7e3fbb6 😄.Fixed in v9 https://github.com/webpack-contrib/sass-loader/releases/tag/v9.0.0 with some hacks, unfortunately, this can lead to loss of performance in some rare cases, we can do nothing here, hope
sass(dart-sass) team improve custom resolving mechanism in future and we can avoid these problems.The algorithm was improved and tested very well, but I’m still worried about some rare cases when we can do something wrong. So feel free to open a new issue with minimum reproducible test repo if you faced with problems, we will fix it.
@nex3 Tired 😞 , I’ve been trying to show you a design error for several months now and you’re not doing anything, I support many webpack packages integrated with many different tools, I do not want to show myself smarter than someone else, but I have enough knowledge to show all integrations problems. And you repeat the same thing several times, completely refusing to understand me. I think you need help from another
sasscore developer(s) here to understand the problems, can you tell who could help with this?I deeply cannot understand why
lessteam pretty quickly understood us and made improvements.What is the problem to implement
sass.resolve/sass.resolver/visitorapi?lesshas ability https://github.com/less/less.js/blob/master/lib/less/environment/file-manager-api.js#L87stylushas ability usingstylus/lib/visitortypescripthas ability using configurations/node APITHE PROBLEMS
Number 1
sass-loaderincludePaths: ['./node_modules/framework/']node_modules/framework/color-utils/index.scssfilecolor-utilspackage withindex.scss-./node_modules/color-utils/index.scss@import 'color-utils';We run
webpack.resolveand return./node_modules/color-utils/index.scsstosass, but it is wrong. Because we did not take into accountincludePaths. Why didn’t we do it? Becausewebpack.resolvedo not useincludePathsfromsassoption. Why are we not doing this? Because it’ssasscare. What if we take care of this? Because we have to duplicate thesasslogic. Could duplication of logic be a bad idea?Lastly you even have
forImportargument here https://github.com/sass/dart-sass/blob/master/lib/src/importer/node/implementation.dart#L95.Number 2
sass-loaderincludePaths: ['./node_modules/framework/']./node_modules/framework/color-utils.scssfilecolor-utilsto./src/utils/my-file-with-utils.scss@import 'color-utils';webpackWe run
webpack.resolveand return./src/utils/my-file-with-utils.scsstosass, but it is wrong. If you try to compilesasswithout webpacksassresolve@import./node_modules/framework/color-utils.scss. We again have a problem with what we need to emulatesassresolution algorithm. And new improvements insassresolutions algorithm will make us fix it again. It’s never ending.Number 3
sass-loader./custom-directory/unknown/index.scss@import 'unknown';SASS_PATHequalscustom-directorywebpackWe run
webpack.resolveand spend time on lookingalias/node_modules/relativepaths/various extensions/other custom configured abilities (many memory and CPU) and no luck. Why did we spend this time/memory/cpu, I don’t know? By runningsass.resolvewe would not have to spend resources.Why do these problems exist?
From source:
We need to emulate logic for everything below
/// 2. Custom importer imports.. If we were the last (i.e.5) it would not be a problem. Above, I have already shown why we do it. Yes we implemented this hack/very terrible solutions https://github.com/webpack-contrib/sass-loader/blob/master/src/webpackImporter.js#L87 (we putworking directory,includePathsandSASS_PATHinincludePathsvariable), but this is not entirely true. For example - we don’t throw an error onfile.extand_file.ext. Yes, we can improve it. But keep track ofsassalgorithm changes is too redundant for us.What am I supposed to do here? Do you suggest me to start implementation and design?
Just say that you don’t want to fix it and save my and your time, it’s not so difficult. I’ll just embed the modified
sasswith fixed algorithm insass-loaderand setup automatic patching and releases. Honestly, I would have done it and no one would have had any problems.@nex3
You still can’t understand me 😞 I’m trying to show what the problem is and you don’t want to understand me for a long time.
I will try to explain everything again.
We emulate
sassresolution algorithm beforewebpackresolution algorithm. We uses it because developer can setupincludePaths,webpackresolver have more ability thansassresolver. Developer can setup ownextensions,mainfiles (index.ext/custom.ext/etc),mainfields inpackage.json(sass,style,mainetc) and more other abilities. He can even setupjsextension, sowebpackresolver returnjsfile. Why? Because webpack is very big ecosystem. Developer can usealias, so@import 'package';can be any resolution. But if developer setincludePathshe wants to load fromincludePathsfirstly and when try to load fromwebpack. Here a lot of use case, really a lot of use case.Without emulation of
sassresolution algorithm if developer setupincludePathsthis can lead to resolutions problems.Here example for
less-loader(no problems with resolving, because they improve it after same request) https://github.com/webpack-contrib/less-loader/blob/master/src/utils.js#L87. You can find that we first calllessbuilt-in resolver https://github.com/webpack-contrib/less-loader/blob/master/src/utils.js#L99, then if he did not resolve, then we callwebpackresolver.It is worth saying that
sassis not fast, so we cached all resolver calls. Without emulation we can’t cache it.I’ve been trying to explain this for a long time, but you either refuse to listen to me or don’t want to, honestly I don’t know.
I’d assume this is still in progress?
Looks like something broken on
dart-sassside when you mixed@importand@use, our importer gets invalid URLs for resolve@importshould support_file.import.extandfile.import.extand prefer using.importfiles@useshould notVery strange, when we use
@useourimporterget those urls:But when we use
@importwe have:Investigate deeply.
@rutwick-alic, this issue and repository has nothing to do with your support request, try asking your question on the Slack channel of Stencil: https://stencil-worldwide.herokuapp.com
Both of these invocations print the same output for me with the latest version of @abhiomkar’s repo. I think this is a legit sass-loader bug.
@nex3, @jathak would it be possible to revisit your implementation of
@usein dart-sass given the issues it is causing? I think @evilebottnawi isn’t the only one who is puzzled by how this breaking change is being handled. I’ve noticed that both of you are Google employees, are you aware that the new feature is also disrupting projects maintained by Google, such as material-components-web?Can you go into more detail about how and under what circumstances these will break? As in, walk me through an example import?
I outlined a couple problems above:
It’s not generally a good practice to add API surface you know is going to be deleted.
New JS APIs have to go through a design process and, ideally, be implemented simultaneously in both Dart Sass and Node Sass. It’s not just a simple switch we can flip. If you’re interested in contributing to this design so it goes faster, you’re more than welcome to pitch in to sass/sass#2509.
In addition, the more we design the API to rely on individual importer authors to correctly implement all the intricacies of Sass’s import order, the more prone those importers will be to errors and inconsistencies like the ones being filed in this issue. Certainly they won’t be future-proof if/when the built-in import logic changes again. It may well be the case that a design that (more explicitly) calls out to the Sass implementation to do this resolution given a base file name is better than one that just throws a bunch of configuration information at the importer and trusts it to do the right thing.
Note that, looking through
getPossibleRequests.js, it looks like there are already several waysthat the webpackimporter doesn’t follow standard Sass load-order conventions:@import "_foo.scss", it’ll also look for@import "__foo.scss".@use "_foo.css"(although arguably this is due to a work-around for https://github.com/sass/libsass/issues/2957).Which isn’t to say this is your fault—load order is complicated and it changes with the language! It’s more to say that the webpack importer shouldn’t have to care about all this logic. Instead, more of it should be offloadable onto the Sass compiler.
I dove into the code again, and as far as I can tell the crucial missing piece doesn’t actually have anything to do with
.import. It’s the last bullet point above: the lack of support for index files. If you set up the loader to look for${request}/{_,}index.s{a,c}ss, @abhiomkar’s original reproduction starts working (although I also had to avoid usingutils.urlToRequest()because it was adding an initial./that webpack didn’t like).@rutwick-alic Seriously?
Because
sassteam do not want to help with the problem and ignore it, here two solutions:webpackresolver, so noalias, no~packagerequests, no other resolution abilities fromwebpackincludePathsfrom allowedsassoptions and do not usesassresolutions algorithm, only packages use@import 'package';andpackage/index.import.extwill not work/cc @nex3 friendly ping
Yes, it is strange.
No, I can’t:
What is a problem to add new argument for
importer?I think it will be a breaking change so adding
isImportas fourth argument is not a problem,node-sassdoesn’t support@use, so fornode-sassisImportwill betrueby default.Without the
isImportargument I can’t solve this issue if I implement.importlogic it is break@uselogic.A huge part of developers use
webpackandsass-loaderso sometime in the past I asked you to pay attention to this problem.I currently have a choice
bootstrap,foundation,bulmaand other projects with@importwill suffer).material-components-web(projects use@use/@forward) will suffer.I care too much about bugs/misleading behaviors/lacks of opportunity for 3d party dependencies. If you want the bug to be fixed, implement 4 argument as soon as possible.
Sorry guys, I can’t do something here.
I’m sorry, I didn’t mean to cast blame—I only meant to explain why you were seeing that output. @abhiomkar and I were actually initially investigating Dart Sass for a bug here before we ended up determining it was more likely a sass-loader issue and filing this.
The module system is informally documented on the Sass website. The section on imports and modules is particularly relevant here, since it describes how import-only files work.
For more detailed information, you can check out the Sass specification, particularly the sections on modules and
@import.Also let’s run:
All work and fine.
But:
No output and no errors