I am using Vue.js with Vitest with the sass loader.
When I use @use 'sass:color'
in an inline scss file or in a component, it seems to override variables which are set in css.preprocessorOptions.scss.additionalData
in my vite.config.ts
file.
The issue is reproduced here: https://stackblitz.com/edit/vitejs-vite-nk8yf5?file=src%2Fstyle%2Fsample.scss
For future reference, the setup is as follows:
./src/style/vars.scss
$sample-var: red;
vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "./src/style/vars.scss" as *;`,
},
},
},
});
./src/style/sample.scss
@use 'sass:color';
.sample-style {
color: $sample-var;
}
Component:
<script setup>
</script>
<template>
<div class="sample-style">Hello sample style</div>
</template>
<style lang="scss" scoped>
@import '../style/sample.scss';
</style>
With this code, I get Undefined variable.
for the $sample-var
in sample.scss
.
However, if I comment out @use 'sass:color';
it works as expected (I can access $sample-var
within my component files.
What is going on here? How can I properly import sass:color
in my component styles, while making a set of variables globally accessible using additionalData
in vite.config.js? I'm interested in learning what the best practice is.
The Scss code defined in additionalData
gets prepended to the <style>
tag of the component. So what the Sass compiler ends up processing is:
@use "./src/style/vars.scss" as *;
@import '../style/sample.scss';
When sample.scss
does not include any @use
statements, as per the documentation:
When Sass imports a file, that file is evaluated as though its contents appeared directly in place of the
@import
. Any mixins, functions, and variables from the imported file are made available, and all its CSS is included at the exact point where the@import
was written.
That means that the above is evaluated similarly to:
@use "./src/style/vars.scss" as *;
.sample-style {
color: $sample-var;
}
However, as per the documentation on importing a module-system file (emphasis mine):
When you import a file that contains
@use
rules, the importing file has access to all members (even private members) defined directly in that file, but not any members from modules that file has loaded.
$sample-var
is a member from a module, and thus sample.scss
does not have access to $sample-var
.