Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure Vue to automatically import some SASS styles into .scss files with the new @use rule?

tl;dr: How to automatically import some .scss files with global styles into both other .scss files as well as into Vue's Single File Components?


I have a Vue project configured to automatically import some global styles:

// vue.config.js

module.exports = {

  // Automatically import global styles:
  css: {
    loaderOptions: {
      scss: {
        prependData: `
          @use "@/global/styles/_Colors.scss";
          @use "@/global/styles/_Mixins.scss";
        `
      }
    }
  }

}

This works perfectly for automatically importing my global styles with @use into every Single File Component:

<!-- Component.vue -->

<template>...</template>

<style lang="scss">
.hero {
  background: Colors.$primary; // _Colors.scss was automatically imported with @use!
}
</style>

But, it doesn't work if I define my component styles in a separate file, and then import that file into the component, like this:

// ComponentStyles.scss

.hero {
  background: Colors.$primary; // Error! "There's no module with the namespace "Colors"
}
<!-- Component.vue -->

<template>...</template>

<style lang="scss">
@use "./ComponentStyles";
</style>

I've tried using the style-resources-loader plugin following the sample configuration in the Vue docs for Automatic Imports, like this:

// vue.config.js

const path = require('path')

module.exports = {
  chainWebpack: config => {
    const types = ['vue-modules', 'vue', 'normal-modules', 'normal']
    types.forEach(type => addStyleResource(config.module.rule('scss').oneOf(type)))
  },
}

function addStyleResource (rule) {
  rule.use('style-resource')
    .loader('style-resources-loader')
    .options({
      patterns: [
        path.resolve(__dirname, './src/global/styles/_Colors.scss'),
        path.resolve(__dirname, './src/global/styles/_Mixins.scss')
      ],
    })
}

And it worked. Kind of. I now had access to my global styles even inside .scss files (not just in SFCs). But, a new error emerged. Importing my local component styles with @use inside a Vue component no longer works.

<!-- Component.vue -->

<template>...</template>

<style lang="scss">
@use "./ComponentStyles";
// Error! @use rules must be written before any other rules.
</style>

I guess that, in the second approach, the style-resources-loader plugin is using @import rules or dumping the content of my global styles above my local @use rules in SFCs. That would result in the error I saw, but I couldn't find any option to control that.


Goal:

I want to be able to automatically prepend the .scss files I import into my SFCs with @use rules that expose my global styles to those files (much like the loaderOptions property in vue.config.js from my first approach allowed me to do in SFCs). I want to keep my SFCs as clean as possible, and that's why I prefer to have my component styles broken down into separate files.

So, is there any way to automatically import some .scss files into both Vue's Single File Components and into other .scss files with @use rules?

Thank you in advance for any help.

like image 283
M2K Avatar asked Sep 05 '25 14:09

M2K


1 Answers

Update: Mostly Solved

I managed to:

  1. Automatically import global Sass styles into all Vue components.
  2. Easily access global Sass styles from .scss or .sass files.

The only slight annoyance is that I have to manually import my global styles into Sass files (they're only automatically imported into Vue components). But, the setup I'm using supports aliases, so I don't need to worry about constructing relative paths or updating my import statements if I move my styling files. Also, unlike my previous setup, the new one has full support for the latest @use syntax.

Setup Guide

Note: I'm now using Vite instead of the Vue Cli.

Note 2: I made a [minimal repo][1] in case you prefer to explore a more detailed demonstration of how to set this up.

vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],

  // Config Docs: https://vitejs.dev/config/#css-preprocessoroptions
  css: {
    // make global variables and mixins available in all Vue components:
    preprocessorOptions: {
      sass: {
        additionalData: `
        @use './src/global/Index' as GlobalStyles
        `
        // ...I chose to merge all my GlobalStyles into one single scope here,
        // but you can also import them individually.
      }
      //...you can change the key above from 'sass' to 'scss' if you use scss in
      // your Vue components. You could also repeat the same settings for both if
      // you alternate between sass and scss in your components. Note that this
      // distinction is not needed for the ".sass" or ".scss"" files you import into your
      // Vue components. Those are handled by the alias resolver below, which will work
      // regardless of the Sass file extension you use.
    }
  },

  resolve: {
    alias: [
      {
        // This will help us use our global styles from regular sass files:
        find: '@styles',
        replacement: path.resolve(__dirname, 'src/global/Index')
      }
    ]
  }
})

Global Variables Example

// Colors.sass
$aquamarine: hsl(160, 100%, 75%)
$deepSlateGray: hsl(160, 25%, 5%)
$faintAqua: hsla(160, 100%, 95%, 0.25)

Global Mixins Example

// Mixins.sass
@mixin useCenteredFlex($direction)
  display: flex
  flex-direction: $direction
  justify-content: center
  align-items: center

Global Styles Aggregator

Note: This is in the same directory as Colors.sass and Mixins.sass, and is the file I'm automatically importing into all Vue components and matching the @style alias to.

// Index.sass
@forward 'Colors'
@forward 'Mixins'

Demo of Accessing Global Styles from a Vue Component

<template>...</template>
<style lang="sass">
body
  @include GlobalStyles.useCenteredFlex(column)  // <- using a globally available mixin
  background-color: GlobalStyles.$deepSlateGray // <- using a globally available variable
</style>

Demo of Accessing Global Styles from a Sass file

// Here we need to reference the alias we set up in vite.config.js to access our GlobalStyles
@use '@styles' as GlobalStyles
  
h1
  color: GlobalStyles.$aquamarine // <- using a global variable


  [1]: https://github.com/mareszhar/demo-asiivwv-so
like image 141
M2K Avatar answered Sep 08 '25 11:09

M2K