Why donate
API Explorer
Upgrade guide
NEW!
The quasar.config file
Convert project to CLI with Vite
Browser Compatibility
Supporting TypeScript
Directory Structure
Commands List
CSS Preprocessors
Routing
Lazy Loading - Code Splitting
Handling Assets
Boot Files
Prefetch Feature
API Proxying
Handling Vite
Handling process.env
State Management with Pinia
Linter
Testing & Auditing
Developing Mobile Apps
Ajax Requests
Opening Dev Server To Public
Quasar CLI with Vite - @quasar/app-vite
Handling Vite

The build system uses Vite to create the UI of your website/app (/src folder). Don’t worry if you aren’t acquainted with Vite. Out of the box, you won’t need to configure it because it already has everything set up.

Updating Vite config

You may have noticed that the vite.config.js / vite.config.ts file does not exist in your Quasar CLI with Vite project. This is because Quasar CLI generates the Vite configuration for you so that you don’t have to worry about it.

In case you need to tweak it, you can do so through quasar.config file > build > extendViteConf like so:

/quasar.config file

build: {
  extendViteConf (viteConf, { isServer, isClient }) {
    // We return an Object which will get deeply merged into
    // the config, instead of directly tampering with viteConf
    return {
      build: {
        chunkSizeWarningLimit: 750
      }
    }
    // equivalent of following vite.config.js/vite.config.ts:
    // export default defineConfig({
    //   build: {
    //     chunkSizeWarningLimit: 750
    //   }
    // })
  }
}

Notice that you don’t need to return anything. The parameter of extendViteConf(viteConf) is the Vite configuration Object generated by Quasar for you. You can add/remove/replace almost anything in it, assuming you really know what you are doing. Do not tamper with the input and output files though or any other option that is already configured by quasar.config file > build.

If you want to add some Vite plugins, see the Adding Vite plugins section below.

Inspecting Vite Config

Quasar CLI offers a useful command for this:

$ quasar inspect -h

  Description
    Inspect Quasar generated Vite config

  Usage
    $ quasar inspect
    $ quasar inspect -c build
    $ quasar inspect -m electron -p 'build.outDir'

  Options
    --cmd, -c        Quasar command [dev|build] (default: dev)
    --mode, -m       App mode [spa|ssr|pwa|bex|cordova|capacitor|electron] (default: spa)
    --depth, -d      Number of levels deep (default: 2)
    --path, -p       Path of config in dot notation
                        Examples:
                          -p module.rules
                          -p plugins
    --thread, -t     Display only one specific app mode config thread
    --help, -h       Displays this message

Adding Vite plugins

Make sure to yarn/npm install the vite plugin package that you want to use, then edit the /quasar.config file:

/quasar.config file

build: {
  vitePlugins: [
    // both are perfectly equivalent:
    [ '<plugin-name>', { /* plugin options */ } ],
    [ '<plugin-name>', { /* plugin options */ }, { server: true, client: true } ]
  ]
}

You can disable a plugin on the client-side or the server-side, which is especially useful when developing a SSR app:

/quasar.config file

build: {
  vitePlugins: [
    // disable on the server-side:
    [ '<plugin-name>', { /* plugin options */ }, { server: false } ],

    // disable on the client-side:
    [ '<plugin-name>', { /* plugin options */ }, { client: false } ]
  ]
}

There are multiple syntaxes supported:

/quasar.config file

vitePlugins: [
  [ '<plugin1-name>', { /* plugin1 options */ }, { server: true, client: true } ],
  [ '<plugin2-name>', { /* plugin2 options */ }, { server: true, client: true } ],
  // ...
]

// or:
import plugin1 from 'plugin1'
import plugin2 from 'plugin2'

vitePlugins: [
  [ plugin1, { /* plugin1 options */ }, { server: true, client: true } ],
  [ plugin2, { /* plugin2 options */ }, { server: true, client: true } ],
  // ...
]

// finally, you can specify using the form below,
// but this one has a drawback in that Quasar CLI cannot pick up
// when you change the options param so you'll have to manually
// restart the dev server
import plugin1 from 'plugin1'
import plugin2 from 'plugin2'

vitePlugins: [
  plugin1({ /* plugin1 options */ }),
  plugin2({ /* plugin2 options */ })
  // ...
]

And, should you want, you can also add Vite plugins through extendViteConf() in the /quasar.config file. This is especially useful for (but not limited to) SSR mode where you’d want a Vite plugin to be applied only on the server-side or the client-side:

import plugin1 from 'plugin1'
import plugin2 from 'plugin2'

build: {
  extendViteConf (viteConf, { isClient, isServer }) {
    viteConf.plugins.push(
      plugin1({ /* plugin1 options */ }),
      plugin2({ /* plugin2 options */ })
      // ...
    )
  }
}

Moreover, don’t forget that your /quasar.config file exports a function that receives ctx as parameter. You can use it throughout the whole config file to apply settings only to certain Quasar modes or only to dev or prod:

export default defineConfig((ctx) => {
  return {
    build: {
      extendViteConf (viteConf, { isClient, isServer }) {
        if (ctx.mode.pwa) {
          viteConf.plugins.push(/* ... */)
        }

        if (ctx.dev) {
          viteConf.plugins.push(/* ... */)
        }
      }
    }
  }
})

Example: rollup-plugin-copy

It is likely that you will need to copy static or external files to your Quasar project during the build to production process, rollup-plugin-copy allows you to copy files and folders when building your app.

/quasar.config file

// ...
  build: {
  // ...
    vitePlugins: [
      [
        'rollup-plugin-copy', {
          targets: [
            { // Syntax code, check doc in https://www.npmjs.com/package/rollup-plugin-copy
              src: '[ORIGIN_PATH]',
              dest: '[DEST_PATH]'
            },
            { // Copying firebase-messaging-sw.js to SPA/PWA/SSR dest build folder
              src: 'config/firebase/firebase-messaging-sw.js',
              dest: 'dest/spa'    // example when building SPA
            }
          ]
        }
      ]
      // other vite/rollup plugins
    ]
  }
// ...

Vite Vue Plugin options

If you need to tweak the Vite Vue Plugin(@vitejs/plugin-vue) options, you can do so through quasar.config file > build > viteVuePluginOptions like so:

/quasar.config file

build: {
  viteVuePluginOptions: {
    script: {
      // example: enable experimental props destructuring
      propsDestructure: true
    },

    template: {
      compilerOptions: {
        // example: enable custom/web element tag detection
        isCustomElement: (tag) => tag.startsWith('my-')
      }
    }
  }
}

Folder aliases

Quasar comes with a bunch of useful folder aliases pre-configured. You can use them anywhere in your project and Vite will resolve the correct path.

AliasResolves to
src/src
app/
components/src/components
layouts/src/layouts
pages/src/pages
assets/src/assets
boot/src/boot
stores/src/stores (Pinia stores)

Adding folder aliases

We will use utils as an example, which may be used as import { formatTime } from 'utils/time.js'. There are two ways to add a folder alias:

  1. Through /quasar.config file > build > alias property. This is the simplest way to add a folder alias. Use an absolute path to your alias. Example:
/quasar.config file

import { fileURLToPath } from 'node:url'

export default (ctx) => {
  return {
    build: {
      alias: {
        utils: fileURLToPath(new URL('./src/utils', import.meta.url))
      }
    }
  }
}
  1. By extending the Vite config directly. Do not assign to viteConf.resolve.alias directly to preserve the built-in aliases, use Object.assign instead or return an Object with your extra aliases. Always use absolute paths.
/quasar.config file

import { fileURLToPath } from 'node:url'

export default (ctx) => {
  return {
    build: {
      extendViteConf (viteConf, { isServer, isClient }) {
        Object.assign(viteConf.resolve.alias, {
          utils: fileURLToPath(new URL('./src/utils', import.meta.url))
        })
      }
    }
  }
}
Using with TypeScript

If you are using TypeScript, you DON’T have to also add the aliases to your tsconfig.json file (nor use packages like vite-tsconfig-paths). These are taken care of by the Quasar CLI by default.

PostCSS

Styles in *.vue files (and all other style files) are piped through PostCSS by default, so you don’t need to use a specific loader for it.

By default, PostCSS is configured to use Autoprefixer. Take a look at /postcss.config.js where you can tweak it if you need to.