'Overriding Vuetify variables when building a Vue2+Vuetify app with Vite

I'm trying to migrate a Vue2+Vuetify app from Vue-CLI/Webpack to Vite. The app has a couple of SCSS files, main.scss and variables.scss with the latter imported by the former.

main.scss

@import 'variables';
// global style rules (omitted)

variables.scss

// override some Vuetify variables and define some variables of my own, e.g.
// Vuetify default is 48px
$data-table-mobile-row-min-height: 32px;

// Increase default height by 10px
// https://vuetifyjs.com/en/api/v-date-picker/#sass-variables
$date-picker-table-height: 252px;

main.scss is imported in the root component, which means that:

  1. rules in main.scss are applied to every component
  2. variables in variables.scss can be referred to in any component without any additional imports
  3. variables defined by Vuetify can be referred to in any component without any additional imports
  4. variables in variables.scss override Vuetify variables with the same name

However, after migrating to Vite, only (1) still worked. I was able to resolve (2) and (3) by adding the following to vite.config.js

export default defineConfig({
  // other config omitted

  css: {
    preprocessorOptions: {
      scss: {
        // Make the variables defined in these files available to all components, without requiring an explicit
        // @import of the files themselves
        additionalData: `@import "./src/styles/variables"; @import "vuetify/src/styles/settings/_variables";`
      },
    },
  },
});

However, it's still the case that (4) no longer works.

As far as I know, the vuetify-loader is responsible for this behaviour when building with Vue-CLI, but it's not clear how to override Vuetify variables when building with Vite?



Solution 1:[1]

This is accomplished with unplugin-vue-components, the Vite equivalent of vuetify-loader.

Configure Vite to use unplugin-vue-components with its Vuetify resolver, which automatically imports the Vuetify components and styles upon use (like vuetify-loader):

// vite.config.js
import { defineConfig } from 'vite'
import Components from 'unplugin-vue-components/vite'
import { VuetifyResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  plugins: [
    ?
    Components({
      resolvers: [VuetifyResolver()],
    }),
  ],
})

Note: SCSS indented syntax is enabled by default, so additionalData must not contain semicolons, and each line must end with the newline character:

// vite.config.js
export default defineConfig({
  css: {
    preprocessorOptions: {
      sass: {
        // ? no semicolons for indented syntax
        // additionalData: `@import "./src/styles/variables"; @import "vuetify/src/styles/settings/_variables";`

        // ?
        additionalData: [
          '@import "./src/styles/variables"',
          '@import "vuetify/src/styles/settings/_variables"',
          '', // end with newline
        ].join('\n'),
      },
    },
  },
})

The Vuetify plugin setup should import from vuetify/lib/framework instead of from vuetify, and it should not import the default Vuetify CSS:

// plugins/vuetify.js
import Vue from 'vue'

// ? defeats dynamic imports from unplugin-vue-components
// import Vuetify from 'vuetify'
// import 'vuetify/dist/vuetify.min.css'

// ?
import Vuetify from 'vuetify/lib/framework'

Vue.use(Vuetify)

export default new Vuetify({/* options */})

demo

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1