Vite Plugin
Warning
Vize is under active development and is not yet ready for production use. Test thoroughly before adopting it in non-trivial projects.
Bundler status:
@vizejs/vite-pluginis currently the most stable bundler integration. For rollup / webpack / esbuild use@vizejs/unplugin, and for Rspack use@vizejs/rspack-plugin. Those non-Vite paths are still unstable and should be treated as experimental.
@vizejs/vite-plugin provides native-speed Vue SFC compilation for Vite projects. It is designed as a drop-in replacement for @vitejs/plugin-vue on Vue 3 SFCs — your existing <script setup> and Options API components work without modification.
Start with Vite+
For combined compilation, native Vue checks, linting, and formatting, keep settings in
vite.config.ts with the Vite+ helper:
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({}).withVue({});
Migration shows exactly which import and plugin calls to replace. The ordinary Vite path below replaces only the compiler.
Drop-in Scope
The drop-in claim is deliberately bounded, so it is worth stating what it does and does not cover:
- In scope — Vue 3 single-file components compiled through Vite, in both
<script setup>and Options API style, including scoped styles, CSS Modules, SSR, and HMR. - Incubating — Vue 2 and 2.7 (
vue.version: "2"/"2.7", orvize({ vueVersion: 2 })). The legacy dialects are off by default and non-invasive: Vize does not compile.vuefiles in those modes, so your existing Vue compiler,vue-loader, or Nuxt 2 setup stays in charge. See Compiler Options. - Out of scope — webpack, rollup, esbuild, and Rspack.
@vizejs/unpluginand@vizejs/rspack-pluginexist but are experimental and carry no drop-in guarantee; see Experimental Bundler Integrations. - Not complete yet — plugin-option parity with
@vitejs/plugin-vue.include,exclude, andisProductionare honored today; every other documented option, the reason it diverges, and the remaining gaps are tracked in #3227.
Installation
Install vp once from the Vite+ install guide, then add the packages:
vp install -D @vizejs/vite-plugin
Add vize as a direct dependency only if your project imports shared config helpers from "vize"
or exposes package scripts such as vize:lint and vize:check.
Basic Usage
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({}).withVue({});
Replace @vitejs/plugin-vue with @vizejs/vite-plugin to compile through Rust. For combined Vite+ check, lint, format, and build tasks, use the Vite+ defineConfig().
TypeScript Vue Imports
Add the plugin package to compilerOptions.types to make direct .vue imports resolvable by
TypeScript without writing a local env.d.ts shim:
{
"compilerOptions": {
"types": ["vite/client", "@vizejs/vite-plugin"]
}
}
This does not require adding vize as a direct project dependency.
For Vite Plus projects, keep the Vite Plus client type and append the plugin package:
{
"compilerOptions": {
"types": ["vite-plus/client", "@vizejs/vite-plugin"]
}
}
Shared native settings
Keep root settings in defineConfig({ ... }) and add native Vue settings directly with
.withVue({ ... }) from @vizejs/vite-plugin/vite-plus. Export that chain without storing it in
an intermediate variable. The CLI and editor read the same project settings.
Keep TypeScript compilerOptions, standard extends and references in
tsconfig.json; Vue template options belong in vueCompilerOptions.
Dedicated vize.config.* files and top-level vize: settings are retired.
See Configuration for migration and
Shared Vue configuration for scoped entries.
Compiler Options
Direct options passed to vize() take precedence, followed by inline config, then discovered project settings and defaults. Use vue: in the Vite configuration; dedicated vize.config.* files are no longer supported. config: false opts out of automatic discovery.
vize({
vueVersion: 3,
sourceMap: true,
ssr: false,
vapor: false,
customRenderer: false,
templateSyntax: "standard",
scanPatterns: ["src/**/*.vue"],
ignorePatterns: ["node_modules/**", "dist/**", ".git/**"],
});
| Option | Where to set it | Description |
|---|---|---|
vueVersion |
vize({ vueVersion }) |
Set 0.11, 1, 2, or "legacy" to run in non-invasive legacy Vue compatibility mode and leave SFC compilation to the host compiler. |
sourceMap |
vue.compiler.sourceMap or vize({ sourceMap }) |
Generate source maps whose sources name the authored .vue file. Defaults to development on, production off unless build.sourcemap is set. |
ssr |
vue.compiler.ssr or vize({ ssr }) |
Force SSR compilation when Vite's SSR build flag is not enough. |
vapor |
vue.compiler.vapor or vize({ vapor }) |
Compile templates through the Vapor backend. |
jsxMode |
vue.compiler.jsxMode or vize({ jsxMode }) |
Default output backend ("vdom" / "vapor") for .jsx/.tsx components. Per-component "use vue:*" directives override it. |
customRenderer |
vue.compiler.customRenderer or vize({ customRenderer }) |
Treat lowercase non-HTML tags as custom renderer elements. Does not match PascalCase tags such as <TresMesh>. |
customElements |
vue.compiler.customElements or vize({ customElements }) |
Tag patterns compiled as custom elements instead of Vue components. Use ["Tres*"] for TresJS PascalCase renderer tags. |
templateSyntax |
vue.compiler.templateSyntax or vize({ templateSyntax }) |
Choose "standard", "strict", or "quirks" template syntax handling. |
whitespace |
vue.compiler.whitespace, vize({ whitespace }), or template.compilerOptions.whitespace |
Use Vue's "condense" (default) or "preserve" template whitespace mode. Vize also accepts "vue2-line-breaks" through its own compiler/Vite option to keep a newline after text or interpolation when Vue 3 would condense it to one space. This is a narrow migration mode, not full Vue 2 whitespace behavior. For Vue 2.7 whitespace: "preserve" output (as used by Vue 2, vue-loader 15 and Nuxt 2), use "vue2-preserve": whitespace next to text and interpolations is kept as written, and whitespace-only runs between elements become one space. |
template.compilerOptions.comments |
vue.compiler.comments or vize({ template: { compilerOptions: { comments } } }) |
Preserve authored template comments in development by default and omit them in production. Set true or false to override either default. Direct native calls use templateComments and default to false. |
experimentals |
vue.experimentals or vize({ experimentals }) |
Fully opt-in Vue RFC and backend experiments. Missing keys, false, and null are off. |
include |
vue.vite.include or vize({ include }) |
Files that the plugin should compile. |
exclude |
vue.vite.exclude or vize({ exclude }) |
Files that the plugin should ignore. |
scanPatterns |
vue.vite.scanPatterns or vize({ scanPatterns }) |
Glob patterns used for startup pre-compilation. |
ignorePatterns |
vue.vite.ignorePatterns or vize({ ignorePatterns }) |
Glob patterns skipped during startup pre-compilation. |
configMode |
vize({ configMode }) |
Use "root", "auto", or false for shared config loading. |
configFile |
vize({ configFile }) |
Load a specific config file. |
config |
vize({ config }) |
Inline shared config for Vite Plus runtime settings. |
handleNodeModulesVue |
vize({ handleNodeModulesVue }) |
Compile .vue files imported from node_modules on demand. |
debug |
vize({ debug }) |
Print plugin debug logs. |
For the full experimentals flag table, opt-in rules, aliases, and shared-config precedence, see
Experimentals.
Common recipes:
// Vapor-oriented build
vize({ vapor: true });
// TresJS PascalCase renderer tags
vize({
customRenderer: true,
customElements: ["Tres*", "primitive"],
});
// Existing templates that rely on parser edge cases, such as
// v-for alias edge parens or `<div />` as a self-closing leaf
vize({ templateSyntax: "quirks" });
// Monorepo package with explicit scan roots
vize({
root: import.meta.dirname,
scanPatterns: ["src/**/*.vue", "examples/**/*.vue"],
});
// Legacy Vue / Nuxt 2 Bridge project with an existing host compiler plugin
vize({ vueVersion: 2 });
vueVersion: 0.11, 1, 2, and "legacy" are host-compiler compatibility modes. Vize does not
compile .vue files in these modes, does not expose the Vue 3 vite:vue API shim, and does not
inject Vue 3 bundler feature flags. Keep the existing Vue compiler plugin, vue-loader, or Nuxt 2's
own compiler configured normally.
How It Works
The plugin intercepts .vue file requests and compiles them using Vize's Rust-native pipeline through Node.js NAPI bindings:
Pre-compilation — At
buildStart, the plugin discovers all.vuefiles and compiles them in batch usingcompileBatch. This triggers Rayon-based parallel compilation on the Rust side, processing all files across all CPU cores simultaneously.On-demand compilation — During development, if a
.vuefile is requested that isn't in the cache (e.g., dynamically imported), it's compiled on-the-fly viacompileFile.HMR — When a
.vuefile changes, only that file is recompiled. The plugin detects whether the change is style-only and applies a style-only HMR update when possible, avoiding a full component re-render.CSS extraction — In production builds, all scoped CSS from Vue components is extracted and merged into
assets/vize-components.css, eliminating per-component style injection overhead.
Compilation Pipeline
.vue file
→ Parser — Tokenizes and parses the SFC structure
→ Semantic analysis — Resolves template expressions and bindings
→ Code generation — Emits optimized JavaScript (VDOM, SSR, or Vapor)
→ Node.js binding — Hands the result to Vite
→ Vite module graph — Served as a virtual module
The same semantic analysis layer is reused by linting and type checking. See Static Analysis for the diagnostic side of the pipeline.
Comparison
| Feature | @vitejs/plugin-vue | @vizejs/vite-plugin |
|---|---|---|
| Language | JavaScript | Rust (NAPI) |
| SFC Compilation | Yes | Yes |
| Template Compilation | Yes | Yes |
| Script Setup | Yes | Yes |
| CSS Scoping | Yes | Yes |
| SSR Support | Yes | Yes |
| HMR | Yes | Yes (style-only optimization) |
| Batch Pre-compilation | No | Yes (parallel via Rayon) |
| CSS Extraction | Per-component | Merged single file |
| Vapor Mode | Experimental | Yes, experimental |
| Plugin Options | Full documented surface | include / exclude / isProduction; see #3227 |
Advanced Features
Batch Pre-compilation
Unlike @vitejs/plugin-vue, which compiles each .vue file on first request, Vize pre-compiles all discovered .vue files at build start using multi-threaded batch compilation. This means:
- Dev server startup — All components are ready before the first page load
- Production builds — Maximum parallelism from the start
Static Asset Rewriting
The plugin automatically rewrites static asset URLs in templates. For example:
<template>
<img src="./logo.png" />
</template>
The src attribute is hoisted to an import statement, allowing Vite to process the asset through its asset pipeline (hashing, optimization, etc.).
Define Replacement
Vite normally skips import.meta.* replacement for virtual modules (prefixed with \0). Vize's plugin manually applies define replacements to ensure import.meta.env.* values work correctly in compiled Vue components.
Per-Environment Isolation
For Nuxt compatibility, the plugin isolates define values per Vite environment (client vs. server/SSR). This prevents client-side environment values from leaking into SSR output.
Style Preprocessors and Pug
<style lang="scss">, sass, less and stylus follow Vue's order: the preprocessor runs first, then Vize scopes its output and resolves v-bind(). <style module> class maps come from your bundler's CSS-module pipeline. Install the preprocessor package (sass or sass-embedded, less, stylus) in your project, as you would with @vitejs/plugin-vue. <template lang="pug"> is compiled by Vize itself, so no extra package is needed. The legacy <template lang="jade"> spelling is accepted as an alias on the same surfaces.
| Surface | scss / sass / less / stylus | pug / jade |
|---|---|---|
| Vite | Vite preprocesses; Vize scopes the result | Native |
@vizejs/unplugin (webpack, Rollup, Rolldown, esbuild) |
webpack uses your loaders; Rollup, Rolldown and esbuild run your installed preprocessor | Native |
@vizejs/rspack-plugin |
Your loaders, with css-loader or native CSS | Native |
vize build |
Runs your installed preprocessor through Node | Native |
vize fmt |
Preprocessor blocks are left byte-identical | Formatted |
vize lint |
Template rules apply; style blocks are not linted as CSS | Template rules apply |
| LSP | CSS completion and hover (indented syntax included); v-bind() go-to-definition; CSS-module class completion in every preprocessor |
Tag completion and go-to-definition |
Nuxt Compatibility
The plugin exposes a compatibility shim for tools that probe for @vitejs/plugin-vue's API (like Nuxt). This means Vize works with Nuxt's built-in Vue integration without special configuration:
// nuxt.config.ts — using the dedicated Nuxt module
export default defineNuxtConfig({
modules: ["@vizejs/nuxt"],
vize: {
compiler: true,
},
});
See Nuxt Integration for more details.
Notes
- The plugin requires
@vizejs/nativefor Node.js NAPI bindings (installed automatically as a dependency) - Vapor Mode compilation is available for Vue 3.6+ (experimental)
- The plugin supports
virtual:vize-stylesfor importing all compiled CSS as a module .jsx/.tsxVue components are compiled automatically through the same plugin — see the JSX & TSX guide- For experimental rollup / webpack / esbuild / Rspack support, see Experimental Bundler Integrations