Can't load global scss variables in Vue SFCs - vue.js

I tried to follow this tutorial to get access to a global file called variables.scss in all SFC files:
https://vueschool.io/articles/vuejs-tutorials/globally-load-sass-into-your-vue-js-applications/
My project uses vue cli 3, so I added the following property to vue.config.js:
{
css: {
loaderOptions: {
sass: {
data: `#import "src/assets/scss/variables.scss";`
}
}
},
}
the variables.scss file looks like this:
// variables.scss
$purple: #5D2D8B;
My component style looks like this:
<!-- Datepicker.vue -->
<style lang="scss" scoped>
.picker {
color: $purple!important;
}
</style>
But I got this error when trying to use the $purple variable
color: $purple!important;
^
Undefined variable: "$purple"
I've also tried to add style-resources-loader vue-cli plugin, but got the same error.
(added this when tried to use it):
{
pluginOptions: {
'style-resources-loader': {
preProcessor: 'scss',
patterns: [
path.resolve(__dirname, 'src/assets/scss/variables.scss')
]
}
}
}
It seems that on .vue files the #import statement is not applied, but in .scss files it is.
Anyone has an idea what is that about?

Related

Importing Scss into vue.js views

I've noticed that if I want to use my _variables.scss I have to import them in every Vue file. My question is, how can I check if I load the same styles multiple times or does Vue saves only once the same scss files on compiling?
This is my code in multiple view files.
<style lang="scss" scoped> #import '~#/abstracts/_variables.scss'; #import '~#/pages/_profile.scss'; </style>
I import _variables.scss in every view where I want to use my scss variables.
This depends on how you have your project setup, for example if you're using webpack you can do something like this where you have your CSS loaders setup:
scss: generateLoaders('sass', {
additionalData: `
#import "#/styles/_variables.scss"
`,
}),
Or if you have a vue.config.js you can do this:
module.exports = {
css: {
loaderOptions: {
sass: {
additionalData: `
#import "#/assets/scss/main.scss"
`
}
}
}
}
Then you will have access to this global SCSS file everywhere in your Vue application.
Side note on the additionalData portion - that will depend on the version of sass loader you're using:
For ^7.x.x use data, and for ^8.0.2 use prependData, finally for 9.0.0+ use additionalData

How do I use `localIdentName` with vue-cli

I'm trying to randomize/minify generated class names.
Currently I'm using a fairly vanilla vue-cli project, and I'm also using Tailwind css which I hope doesn't complicate anything.
Currently this is how far I got in my vue.config.js by reading vue-loader docs, this, and this, however this only works half way... my CSS minifies perfectly, however my vue component classes dont' change, so its like it's not parsing *.vue files.
I thought this could be because I notice it mentioning using <style scoped> but with Tailwind you don't need style tags in your components. Quite literally 100% of the css is contained in my src/assets/styles/main.pcss file, which consists of a few #import statements and that's it.
module.exports = {
css: {
requireModuleExtension: false,
loaderOptions: {
css: {
modules: {
localIdentName: '[hash:6]',
},
},
},
},
chainWebpack: config => {
// disable eslint temporarily
config.module.rules.delete('eslint');
},
};
And my tailwind config:
module.exports = {
future: {
purgeLayersByDefault: true,
removeDeprecatedGapUtilities: true,
},
plugins: [],
purge: [
'./src/**/*.html',
'./src/**/*.vue',
],
theme: {},
};

Vue invalid CSS - expected 1 selector or at-rule,

I'm trying to npm run serve in Vue and receiving the following error:
Failed to compile.
./src/App.vue?vue&type=style&index=0&lang=sass& (./node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--9-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=style&index=0&lang=sass&)
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
SassError: Invalid CSS after " ": expected 1 selector or at-rule, was "{"
on line 1 of /Users/MatthewBell/GitHub/pollify/client/src/App.vue
>> {
^
Clearly it says the error is in App.vue and seems like a misplaced curly brace.
But if check in that file there aren't even any curly braces there:
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link>|
<router-link to="/about">About</router-link>
</div>
<router-view />
</div>
</template>
<style lang="sass">
#app
#extend %global-styles
</style>
..And the file of class being extended.. main.sass is shown below. None of the imported sass sheets have curly braces either, so I'm sitting here very confused about the error message.
// Importing all our globally accessible stylesheets
#import ./reset
#import ./variables
#import ./mixins_and_placeholders
%global-styles
font-family: $font
-webkit-font-smoothing: antialiased
-moz-osx-font-smoothing: grayscale
background-color: $grey-3
color: $text-black
I also searched this question on StackOverflow and some people seem to say it can be an issue with your config file, but I cant find any issues with my vue.config.js:
// vue.config.js
module.exports = {
css: {
loaderOptions: {
// pass options to sass-loader
// #/ is an alias to src/
// so this assumes you have a file named `src/variables.sass`
// Note: this option is named as "data" in sass-loader v7
sass: {
prependData: `
#import "#/styles/main.sass"
`
}
}
}
};
This was working fine before so it's not an issue with the prepend data path.
As Phil mentioned in the comments. The indented #import "#/styles/main.sass" in my config file vue.config.js was causing the issue, since backticks preserve indentation. The following syntax solves it:
// vue.config.js
module.exports = {
css: {
loaderOptions: {
// pass options to sass-loader
// #/ is an alias to src/
// so this assumes you have a file named `src/variables.sass`
// Note: this option is named as "data" in sass-loader v7
sass: {
prependData: `#import "#/styles/main.sass"`
}
}
}
};

sass-loader can't resolve #use rule

I'm working on a vuejs app and I'm trying to import my variables files using the #use rule within prependData in sass-loader, but it seems not working properly. Using #use import does not work and I receive erros about variables. But using #import everything goes fine. Am I doing something wrong or getting the wrong concept about #use rule?
Using #import in prependData works:
css: {
loaderOptions: {
sass: {
implementation: require('sass'),
sassOptions: {
indentedSyntax: true
},
// prependData: `#use '~abstracts/variables'` //this does not work
prependData: `#import '~abstracts/variables'` //this works
}
}
}
Using #use does not work:
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
SassError: Undefined variable.
╷
15 │ color: $chuck
│ ^^^^^^
╵
My package.json:
"sass": "^1.26.3",
"sass-loader": "^8.0.2"
My component:
<style lang="sass">
.title
color: $chuck
</style>
My variables.sass file:
$chuck: #BADA55
TIA
I just figured out what I was missing.
Just add as *:
css: {
loaderOptions: {
sass: {
implementation: require('sass'),
sassOptions: {
indentedSyntax: true
},
prependData: `#use '~abstracts/variables' as *`
}
}
}
I'm just getting used to this new way of using sass.

How do I #extend external CSS classes in a Vue component?

For example, if I have something like this in my component:
<style lang="scss" scoped>
.color-blue {
color: blue;
}
.orange-blue {
#extend .color-blue; // This works!
#extend .bg-orange; // .bg-orange is defined in another css file somewhere. This doens't work
}
</style>
I get an error that says
".orange-blue" failed to #extend ".bg-orange".
The selector ".bg-orange" was not found.
I've read that I can add
#import 'path/to/orange.css'
to my style block, but that doesn't seem to do the trick here. Also, wouldn't that result in the CSS being repeated for every component that imports it?
Import the file with other styles like that
<style lang="scss" scoped>
#import '~styles/mixins';
...
</style>
or use the usual path
#import '../../../styles/mixins';
You can do it the following way:
Create the file containing the class you want to extend:
src/styles/style.scss
.my_class_to_extend {
backgroud-color: aqua;
}
In your vue.config.js file you add the following pointing to your file:
module.exports = {
css: {
loaderOptions: {
sass: {
data: `#import "#/styles/style.scss";`
}
}
}
}
After that you can extend in your vue component without problems:
...
<style lang="scss" scoped>
.my_extended_class {
#extend .my_class_to_extend;
}
Note that to use that you need scss files all along, not css.
In short, you can not extend css class in *.scss file by importing plain *.css file. Scss compiler will throw an error SassError: The target selector was not found.
The easy way is to rename referenced *.css file to *.scss. So outcome would be like #import 'path/to/orange.scss'