Separate global basic styles from every page using webpack in vue-cli3 - vue.js

I'm using Vue-cli3.x, which is a multiple-pages project. I'm using SCSS in this project and separating the global basic styles with loaderOptions as following:
The styles relations like this: basic styles ---> components' styles ---> pages' styles
But after I building my project, I found my CSS files include basic styles more than once.
EX: dashboardAirLeft page includes chunk-common.css and dashboardAirLeft.css, however in chunk-common.css and dashboardAirLeft.css all have normalize.scss code, like following:
And my production's Webpack config like this:
My destination is to separate the common code from my page-name css file

Using loaderOptions data property means that the files you import will be imported into every single components <style> tag. So each page-name css file will also import all three of the scss files you've defined. Instead, you probably want to import the common scss files only once in the App.vue component (or main entrypoint):
App.vue
<template>...</template>
<script>...</script>
<style lang="scss">
#import "#/assets/styles/scss/normalize.scss"
#import "#/assets/styles/scss/base-style.scss"
</style>
However, you do want the variables-custom.scss file imported into each page though so that you have access to your scss variables in each component. So you should leave only variables-custom.scss in your loaderOptions:
vue.config.js
css: {
loaderOptions: {
sass: {
data: "#import '#/assets/styles/scss/variables-custom.scss'"
}
}
}

Related

Importing global scss style in Vue application together with separate mixin and variable scss files

I am building Vue 3 app with scss. I have 3 stylesheet files - _mixins.scss, _variables.scss and base.scss. I am importing the mixins and variables files in vue.config.js as I read here, so I can use these mixins and variables in all my other components without needing to import them manually in all components.
However, I have also base.scss file, where I want to have global styles for my website (e.g. general styles for headings, etc.). I do not want to import this file in vue.config.js, because it would mean, that this file would be repeatedly included in all my components. So I tried to import it in App.vue via #use "styles/base"; or in main.js using import "styles/base.scss";.
Unfortunately in both cases, Sass compiler throws this error:
Syntax Error: SassError: #use rules must be written before any other rules.
╷
6 │ #use "styles/base";
│ ^^^^^^^^^^^^^^^^^^
╵
D:\PWND\pwnd_ui_poc_js\src\App.vue 6:1 root stylesheet
I do not really know, how I should do it correctly. For the sake of completeness, I am including the base structure of my files:
// _variables.scss
$baseGreen: #24ff00;
// _mixins.scss
#forward "variables";
#mixin section-heading {
color: $baseGreen;
}
// base.scss
#forward "mixins";
#forward "variables";
.section {
color: $baseGreen;
&-heading {
#include section-heading();
}
}
If you have any idea, how I should do this correctly, I would really appreciate your help. Thank you! :)
I'm using that configuration to load global variables for any component:
vue.config.js
module.exports = {
css: {
loaderOptions: {
sass: {
prependData: `#import '#/scss/_variables';`,
}
}
},
}

How to change primary color on primevue?

I use Primevue on a vue.js project, with the theme Deep Purple that I import this way:
import 'primevue/resources/themes/mdc-light-deeppurple/theme.css';
Now I'd just like to modify the primary color set in the theme (#673AB7) by a custom one.
How can I do this ?
I copied the primevue theme .css file to src/assets/_theme.scss (note .scss).
Then in App.vue, instead of importing the vue theme, import _theme.scss
<style lang="scss">
#import './assets/_theme.scss'; // copied from '~primevue/resources/themes/nova/theme.css'
#import '~primevue/resources/primevue.min.css'; //core css
#import '~primeicons/primeicons.css'; //icons
...
Next, in _theme.scss, search and replace all values of the current primary-color hex code with $primary-color. This should make a bunch of replacements.
Then just set a new $primary-color variable at the top of the file.
//_theme.scss
$primary-color: #000;
If you want to define all your scss variables in a single file and make them available to every vue component without needing to #import them explicitly, then create/add the following to vue.config.js in your project root.
module.exports = {
css: {
loaderOptions: {
scss: {
prependData: `#import "#/assets/_variables.scss";`
}
}
}
};

Overriding Vuetify variables

I'm using Vuetify in my project, and I want to use a variable file to override the styles generated by Vuetify.
I'm loading the components and their corresponding styles using the a-la-carte method, so I'm NOT importing the Vuetify SASS file using this:
#import '~vuetify/src/styles/styles.sass'
// Not using this method because I don't want to generate styles that are not being used by
// vuetify components I'm not using
Also, my project is using *.scss, not *.sass.
I'm also injecting a global SCSS file containing mixins and other variables in my vue.config.js:
css: {
sourceMap: productionSourceMap,
loaderOptions: {
scss: {
prependData: `#import '#/scss/_common.scss';`
}
}
},
I included a Vuetify variable, $border-radius-root, in that common.scss file, but it doesn't seem to have any effect.
Any idea how to do what I want without having to write entirely new CSS rules to override Vuetify's generated stylesheet? Basically I want to change the units that Vuetify uses using their own stylesheet generator.
Actually the solution is, and I'm dumb for not thinking of this before, to add another loader to vue.config.js:
css: {
sourceMap: productionSourceMap,
loaderOptions: {
scss: {
prependData: `#import '#/scss/_common.scss';`
},
sass: {
prependData: `#import '#/sass/_vuetify-variables.sass';`
}
}
},
Since vuetify is using sass as the css pre-processor, it needs sass-loader to handle the variable overrides and apply it to the framework.
If you are using Nuxt:
you can add customVariable path in your nuxt.config.js file, in vuetify object
Note you have to enable treeShake. This option is required for custom SASS variables to work
example:
vuetify: {
// usually file should be in assets folder
customVariables: ['~/path/to/variables.scss'],
treeShake: true,
}
If you are using Vue CLI:
Create a folder with name: sass, scss, or styles
Create new file inside this folder and name it: variables.scss or variables.sass
vuetify-loader will automatically bootstrap your variables into Vue CLI’s compilation process, overwriting the framework defaults.
From Vuetify docs:
If you have not installed Vuetify, check out the quick-start guide. Once installed, create a folder called sass, scss or styles in your src directory with a file named variables.scss or variables.sass. The vuetify-loader will automatically bootstrap your variables into Vue CLI's compilation process, overwriting the framework defaults.
So, the vuetify-loader automatically loads #/scss/variables.scss in a Vue CLI project, so you could set $border-radius-root in that file, and it will overrride the framework default.

Vue SFC add global Sass variables to all components

Im my webpack config I add a path
"mixins": path.resolve(
__dirname,
"resources/assets/sass/mixins/mixins.scss"
),
Which means in all my single file components I use
<style lang='scss' scoped>
#import '~variables';
This works fine but what I am finding is this file is used in 95% of components so the import really is unnecessary. I want these vars available everywhere.
How can I globally add my SASS to my single file components without the need for the import in every file?
Well, Load your common CSS from Webpack and make it available globally for all the component. Webpack configurations are as below.
sass-loader also supports a data option which allows you to share common variables among all processed files without having to explicit import them
module.exports = {
css: {
loaderOptions: {
sass: {
data: `
#import "#/scss/_variables.scss";
#import "#/scss/_mixins.scss";
`
}
}
}
};
In here, specifing the sass loader under the loaderOptions option. Just like that, all the code in those files will be available in the global scope. So from any component we can use it out of the box:
And now you can able to access the variable in your Vue SFC without importing it.
<style lang="scss">
.classroom {
/* No need to import, it just works \o/ */
background: $bg-classroom;
}
</style>
Reference Official Docs here
Hope this helps!

Importing external sass in Vue

I'm importing bulma into Vue (installed via vue init webpack-simple ) and I can't seem to figure out how to get it to load my own external sass files.
I have it set up like this:
<style lang="sass" src="./sass/initial-variables"></style>
<style lang="sass" src="bulma"></style>
The tag pulling bulma in works just fine, but I get an error looking for my initial variables file:
ERROR in ./src/App.vue
Module not found: Error: Can't resolve './sass/initial-variables' in
'/Users/johnbriggs/Sites/mimismarket/src'
In my src folder, I have a sass directory with initial-variables.sass as a file.
What am I missing here?
It looks like you're missing the .sass. extension in your <style> tag. Webpack might take that relative import literally.
One thing I like to do to keep my single-file components clean is to have one <style> tag and then #import my SASS files:
<style lang="sass">
#import 'bulma'
#import './sass/initial-variables' // we don't need the extension here
</style>
Another thing to keep in mind is that you can import CSS/SASS files in your JavaScript, too. It's really handy for global stylesheets:
// main.js
import 'bootstrap/dist/css/bootstrap.min.css'
You can do the following in your webpack.config:
loader: 'vue-loader',
options: {
extractCSS: true,
loaders: {
sass: ExtractTextPlugin.extract({
use: 'css-loader!postcss-loader!sass-loader?indentedSyntax&data=#import "./sass/initial-variables.sass"',
fallback: 'vue-style-loader'
})
}
}