beeftony
beeftony

Reputation: 307

How can I make a sass file global instead of importing it in every file and bloating bundle size?

Question
How can I globally import variables.scss 1. without importing them in every file and 2. by referencing instead of duplicating them in my build?

Setup
I use Vue2 and laravel-mix and I have index.scss imported in my main.js

variables.scss

$--test: #ff0000;

index.scss

@import 'variables';

.dashboard-title {
    color: $--test;
}

This colors the title red. But when I try to do the same thing inside of the component, it doesnt work:

<style scoped lang="scss">
    .dashboard-title {
       color: $--test;
    }
</style>

This doesn't work, but I proved that index.scss is global in my first example. How is variables.scss not global, when I import it in my global index.scss?

I can fix the error by importing the variables file in the component, but by doing this, I essentially duplicate the whole variables.scss file every time I import it in a vue component. I found this out by analyzing my bundle with a webpack bundle analyzer, this is the output: webpack bundle analysis image
(all blue crossed parts are increased in size because the variables file is imported, this isn't a big problem now, but this will exponentially increase my bundle size with time)
It would reduce my bundle size by atleast 20% right now...

How can I reference the variables.scss file instead of duplicating its content?

What I've tried:
https://css-tricks.com/how-to-import-a-sass-file-into-every-vue-component-in-an-app/ (I wasn't able to "migrate" this to a laravel-mix config)
I've also tried using purgeCss to remove duplicate css, this just completely messed up my styles but reduced the bundle size by 50% lol
Adding this to the webpack.mix.js

mix.webpackConfig({
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: [
                    {
                        loader:  'sass-loader',
                        options: {
                            //this might be "data" or "prependData" depening on your version
                            additionalData: `@import "./resources/js/styles/variables.scss";`
                        }
                    }
                ]
            }
        ]
    }
})

This does make the variables global, but imports(duplicates) them for every vue component, even if they aren't being used.

Edit: This only is an issue, when the imported file is relatively big. In my project, the imported file itsself imported a theme scss (to get access to the themes variables), which ultimately copied this whole thing everywhere I needed the variables.
I fixed this by defining my custom variables in a seperate file and using those variables in the "overwriting-variables" file, something like this:
custom-variables.scss

$red: #ff0000;

overwriting-variables.scss

import 'theme.scss'; //this bloated my project
import 'custom-variables';

$--theme-red: $red

And when I needed this theme color in my vue components I just imported the custom-variables.scss instead of overwriting-variables.scss.
This does fix my bloating issue, but doesn't fully solve the problem, I still have multiple instances of the custom-variables.scss in my project, it just doesn't matter (yet) because its really small. So I'd be still happy to hear about other solutions!

Upvotes: 4

Views: 2387

Answers (2)

beeftony
beeftony

Reputation: 307

So I got it working with laravel-mix like this:

mix.webpackConfig({
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: [
                    {
                        loader:  'sass-loader',
                        options: {
                            //this might be "data" or "prependData" depening on your version
                            additionalData: `@import "./resources/js/styles/variables.scss";`
                        }
                    }
                ]
            }
        ]
    }
})

Not sure yet if this prevents the duplication though

Edit: It does not prevent duplication, it does increase the bundle size in every vue component. So I now have a 150% bigger bundle, because the variables file is imported in every single vue component. Even if the variable isn't even used.

Upvotes: 0

Abregre
Abregre

Reputation: 480

If you import every .scss in your index.scss, then every variable should work. Try this in your vue.config

  css: {
        loaderOptions: {
            // by default the `sass` option will apply to both syntaxes
            // because `scss` syntax is also processed by sass-loader underlyingly
            // but when configuring the `data` option
            // `scss` syntax requires an semicolon at the end of a statement, while `sass` syntax requires none
            // in that case, we can target the `scss` syntax separately using the `scss` option
            scss: {
                prependData: `@import "@/style/index.scss"`
            }
        }
    },

Upvotes: 1

Related Questions