How to efficiently add global css using nuxt3 and vite? - vue.js

I have global sass being included in my project and i cant find an efficient way to add it to the project.
there seems to be 2 popular ways to add css in your project.
vite: {
plugins: [svgLoader()],
css: {
preprocessorOptions: {
scss: {
additionalData: `
#import "~/assets/styles/main.scss";
`,
},
},
},
using vite seems to work but it also seems to inject itself into every component i use, so when i generate my project, i can see my css is repeated multiple times, some files as much as 300 times. the issue is found here on vites side https://github.com/vitejs/vite/issues/4448
css: ["#/assets/styles/main.scss"],
the above option seems to not do it for every component, but normal scoped sass in .vue files doesnt pick up sass variables and mixins on compilation using this method

using additionalData adds it to every page. this item is only meant for mixns and vars, which dont translate into permanent css when built.
basically use only vars in mixins in additionalData then use your global.scss in in css

Related

My Vue3 Class Component Typescript application gets slower to compile/build when I import bootstrap

I realized that my application was much slower to build with vue-cli (either a build production or a simple dev server).
I import bootstrap this way in a SCSS file that re-writes some rules that is imported in all my other SCSS components.
#import "bootstrap/scss/bootstrap";
Here are the build time comparison screens :
Build with bootstrap
Build without bootstrap
I hope you can help me :)
I solved my problem by removing the imports from my components and adding my scss file in the 'loaderOptions' like as below
module.exports = {
...
css: {
loaderOptions: {
scss: {
additionalData: `#import "~#/assets/base.scss";`
},
}
}
};

Importing SCSS variables in Vue components

I recently switched from Vue-CLI to laravel-mix, the usage of SCSS variables worked perfectly with Vue-CLI and now doesnt seem to work anymore at all after I switched to laravel-mix.
Vue-CLI just handled everything for me and I feel like I have to configure something to get the variables to work in laravel-mix.
This is what I've tried (and what worked with Vue-CLI):
// vue component
import variables from "#/styles/variables.scss";
// ...
data() {
return {
variables
}
}
methods: {
test() {
console.log(this.variables)
}
}
// scss
$variable: #FFFFFF;
:export {
variable: $variable;
}
Edit: To clarify, this log outputs an empty object, not undefined.
For this thing to work you need to follow that particular steps
Make Your Variables File. As you made your scss file inside your style its not good you need to make inside /assets/sass/
Add Variables File To App.scss. For that thing you need to import newly create file inside your app.scss by #import 'folder/file';
Add Alias To webpack.mix.js. What we essentially need to do is define an alias or variable that contains the path to our sass directory so we can include that SASS in our Vue components. Just add alias like this in your webpack
resolve: {
alias: {
'#': path.resolve('resources/assets/sass')
}
}
Last thing add Navigation Vue Component. You can import scss variables by adding #import '~#/folder/fie.scss'; in the vue component

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 SCSS file in Vue SFC components without duplication with Webpack

When I try to access a scss file in all my Vue SFCs the styles are duplicated causing large css bundles and Dev Tools to crash when style debugging
I am using Webpack 4 and webpack-dev-server to build and run development services with hot reload. I did not create the project with Vue CLI.
I have quite a lot of SFCs (~50) and a sass file (index.scss) that contains global styles and variables. I need to be able to use the styles and variables in index.scss across my SFCs. My current approach is using the data option in my Webpack sass-loader.
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.js$/,
loader: 'babel-loader',
},
{
test: /\.scss$/,
use: [
isDev ? { loader: 'vue-style-loader', options: { sourceMap: hasSM }} : {loader: MiniCssExtractPlugin.loader },
{
loader: 'css-loader',
options: {
sourceMap: hasSM
}
},
{
loader: 'sass-loader',
options: {
sourceMap: hasSM,
data: `#import "#/styles/index.scss";`
}
}
]
}
]
}
This is successful, however I am noticing my index.scss styles included in every component. Local development with devserver is almost impossible because the duplication across 50 components is so vast and devtools can't cope. When I do a build to extract the css then I can see the duplication and the app.css file is huge. I can use a minifying process for deployments but this is not suitable at all for local development.
I have tried other approaches such as removing the data option from sass-loader using import ./styles/index.scss in my main.js file instead, however this fails to build because it can't find the variables I use in my SFCs.
Please see my code snippet for roughly how I have my loaders set up. I feel as if there is a better way to do this, whether it's using different loaders/plugins and I am open to using different approaches
I managed to solve. Essentially when every Vue component was being processed then the sass-loader was importing my global sass file that included Variables, Mixins and most importantly my Styles. The import statement in my main.js doesn't work because the Variables and Mixins are not available by the time the component is being processed.
So I only need to import Variables and Mixins in my components and the Styles can be external and included in my main.js. Since Variable and Mixins are just being included when required (with #include statements), then there is no duplication since it's getting compile to CSS.
So I split my Styles and Variables and Mixins into separate variables
Styles => styles.scss
Variable and Mixins => variableMixins.scss
then import ./styles/styles.scss in my main.js
and my webpack sass-loader would be like
{
loader: 'sass-loader',
options: {
sourceMap: hasSM,
data: `#import "#/styles/variableMixins.scss";`
}
}
Been trying to solve this for too long.
This solution works but isn't perfect for me because I want to keep variables and global styles for specific things together.
_typography.scss, for example should contain general styles and variables relating to global line-height and vertical rhythm.
Then more granularly, a component such as _H1.scss would contain it's own sandboxed styles.
I don't want those general styles duplicated for every component.
The value of using CSS is sharing styles and being able to adjust and rebrand in a project globally. Components do the opposite of this by sandboxing everything.
I think CSS is currently at odds with componentized development and perhaps the answer may be to create a new approach where we use 'component ecosystems' to create relationships between otherwise dumb nodes.
A bit like how we use revealing module patterns in JS.
We ended up splitting up css into separate files (one per component), imporing them all into index.scss and importing index in App.vue`
import '#/scss/index.scss'
This eliminated lots of bloat / duplication and significantly simplified workflow: using sourcemaps + workspaces we can now edit scss directly in devtools and it won't break layout or multiply <style> tags or do any other quakery described all over Webpack's and vue-cli's github issues.
Surprisingly, even code-splitting for css still works, and dynamically loaded modules have their separate css files.
If you need scoping (which you'd need), just use id="component-name" on main node and wrap your scss in
#component-name {
...
}
It amazes me how unsupported modern css techniques by Devtools, Webpack etc. Every aspect is full of bugs and only simpliest scenarios sort of work out of the box (if work at all).