Module-level aliases don't work
Opened this issue · 3 comments
Bug report
Actual Behavior
Although this loader does support resolve.alias at the top level of the Webpack config, it seems module-specific aliases are ignored (module.rules[i].resolve.alias). This results in Can't find stylesheet to import errors, which occurs for both @use and @import. One reason for module-level aliases is so that every rule can have its own aliases, without any risk of accidentally importing SASS into TypeScript for example (or vice versa even).
ERROR in ./sass/entry.scss (./sass/entry.scss.webpack[javascript/auto]!=!./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[0].use[1]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[0].use[2]!./sass/entry.scss)
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
Can't find stylesheet to import.
╷
1 │ @import '@aliased/import';
│ ^^^^^^^^^^^^^^^^^
╵
sass/entry.scss 1:9 root stylesheet
@ ./sass/entry.scss
This error seems to originate from sass-loader if I'm interpreting this correctly, which is why I created the issue here and not elsewhere.
Expected Behavior
Perhaps there is a way to just ask Webpack what aliases are relevant for the current loader/rule? That way it will keep working even if they ever add aliases at more levels.
How Do We Reproduce?
- Clone the reproduction repo
- Run
npm iof course - Now you can do either
npm run build-failornpm run build-good
I only used @import in this example because it's closer to my actual scenario (can't use @use due to dependencies), and I figured it's pretty redundant to show @use since the behaviour is exactly the same anyway.
Please paste the results of npx webpack-cli info here, and mention other relevant information
System:
OS: macOS 14.4.1
CPU: (12) arm64 Apple M2 Pro
Memory: 116.09 MB / 16.00 GB
Binaries:
Node: 23.6.1 - /opt/homebrew/bin/node
Yarn: 1.22.22 - /opt/homebrew/bin/yarn
npm: 10.9.2 - /opt/homebrew/bin/npm
Browsers:
Chrome: 133.0.6943.53
Safari: 17.4.1
Packages:
css-loader: ^7.1.2 => 7.1.2
sass-loader: ^16.0.4 => 16.0.4
webpack: ^5.97.1 => 5.97.1
webpack-cli: ^6.0.1 => 6.0.1
That's expected, because you set it not for SASS, you set it for JS (under the hood webpack convert CSS into JS)
Please use on global level:
// ...
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
runtime: false,
}),
],
resolve: {
byDependency: {
"sass": {
extensions: ['.scss'],
alias: {
'@aliased': path.resolve(__dirname, 'sass', 'alias'),
},
}
}
},
module: {
rules: [
// ...Just comment:
{
loader: MiniCssExtractPlugin.loader,
},
and use on a module level:
{
test: /\.scss$/,
exclude: /node_modules/,
resolve: {
byDependency: {
"sass": {
extensions: ['.scss'],
alias: {
'@aliased': path.resolve(__dirname, 'sass', 'alias'),
},
}
}
},
use: [
/*{
loader: MiniCssExtractPlugin.loader,
},*/
{
loader: 'css-loader',
options: {
sourceMap: true,
url: false,
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
sassOptions: {
silenceDeprecations: ['import'],
},
},
},
],
},And it will work, the main problem here is what this code applied to JS (mini-css-extract-plugin doing it in importModule), this is such a design, we are working on built-in CSS support right now inside webpack and this limitation will not exist anymore.
Also any module can contain different resolve logic, for example you can have mixed require() and import() in your file and so we should apply options by dependencies (same for other things in SASS you can have pure CSS and SASS imports and they works different too), otherwise resolver will be broken and that is why I strongly recommend use byDependency, global options when you really want to make aliases across any dependecies
So I want to say it is mini-css-extract-plugin limitation, because even using (without byDependency will work if you comment mini-css-extract-plugin):
resolve: {
extensions: ['.scss'],
alias: {
'@aliased': path.resolve(__dirname, 'sass', 'alias'),
},
},So no problems with sass-loader