'The `/deep/` selector is not working using sass-loader in my VueJS application
In my Vue 2.6.10 webpack application I am trying to add SASS as our team wants to migrate our legacy application from LESS to SCSS. In my package.json
I have installed these to my devDependencies
per these docs:
- sass (v.1.32.8)
- sass-loader (v10.1.1)
Then installed node-sass
(v5.0.0) to my dependencies
.
My node
version is: v15.4.0. According to these docs this is the correct version for node-sass
v5+.
In my Vue components I am trying to use the /deep/
, ::v-deep
, or >>>
selectors. I threw together a working playground where I have a ParentComp.vue
target a ChildComp.vue
's inner styles using /deep/
like this:
<style lang="scss" scoped>
.parent-container {
& /deep/ .child-comp {
background-color: tomato;
color: white;
}
}
</style>
Yay! It works great in my playground using the same versions of things that I have control over in that playground.
In my application when I try this exact same setup I get this compile error:
./src/components/MenuBarComp.vue (./node_modules/css-loader/dist/cjs.js?
{"sourceMap":true}!./node_modules/vue-loader/lib/style-compiler?
{"optionsId":"0","vue":true,"id":"data-v-4630c6ac","scoped":true,"sourceMap":true}!
./node_modules/sass-loader/dist/cjs.js?
{"additionalData":"/n @import /"@/styles/_variables.scss/";/n ","sourceMap":true}!
./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/components/MenuBarComp.vue)
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
SassError: expected selector.
╷
77 │ & /deep/ .child-test{
│ ^
╵
src/components/MenuBarComp.vue 77:5 root stylesheet
According to many other suggestions which I have tried, I should try using ::v-deep
or >>>
. When I try to use these selectors it compiles fine and no longer throws an exception, but nothing happens. No CSS is actually rendered like .parent[data-23423423] .child {}
. But then I see other articles about how this is not supported in SCSS.
So then I go back to trying to figure out what could cause this error and I have tried dozens of things over the course of several days to try and fix this issue like:
- downgrading node-sass / sass / sass-loader versions to other versions to try and get things to work
npm rebuild node-sass --force
rimraf
ingnode_modules
- Clearing entire
npm cache
and many other things
I already have several pre-existing CSS related packages in my package.json
:
- css-loader (v.3.1.0)
- less (v3.0.4)
- less-loader (v4.1.0)
- mini-css-extract-plugin (v0.6.0)
- optimize-css-assets-webpack-plugin (v5.0.3)
- postcss-import (v11.0.0)
- postcss-loader (v2.0.8)
- postcss-url (v7.2.1)
- vue-style-loader (v3.0.1)
Finally here is how my loaders are setup in webpack:
function generateLoaders(loader, loaderOptions) {
const loaders = options.usePostCSS
? [cssLoader, postcssLoader]
: [cssLoader];
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap,
}),
});
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return [MiniCssExtractPlugin.loader].concat(loaders);
} else {
return ['vue-style-loader'].concat(loaders);
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass'),
scss: generateLoaders('sass', {
additionalData: `
@import "@/styles/_variables.scss";
`,
}),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus'),
};
};
How can I get the /deep/
selector to work?
Solution 1:[1]
This is because /deep/
is not supported by sass
. You need to explicitly set your sass-loader
to use node-sass
like this:
loader: 'sass-loader', options: { implementation: require('node-sass')
sass-loader
has a note on their page that says:
Beware the situation when node-sass and sass were installed! By default the sass-loader prefers sass. In order to avoid this situation you can use the implementation option.
The implementation options either accepts sass (Dart Sass) or node-sass as a module.
So your specific code would end up being as sass-loader
uses:
scss: generateLoaders('sass', {
implementation: require('node-sass'),
additionalData: `
@import "@/styles/_variables.scss";
`,
}),
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | maxshuty |