Vize

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-plugin is 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", or vize({ vueVersion: 2 })). The legacy dialects are off by default and non-invasive: Vize does not compile .vue files 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/unplugin and @vizejs/rspack-plugin exist 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, and isProduction are 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:

  1. Pre-compilation — At buildStart, the plugin discovers all .vue files and compiles them in batch using compileBatch. This triggers Rayon-based parallel compilation on the Rust side, processing all files across all CPU cores simultaneously.

  2. On-demand compilation — During development, if a .vue file is requested that isn't in the cache (e.g., dynamically imported), it's compiled on-the-fly via compileFile.

  3. HMR — When a .vue file 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.

  4. 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/native for Node.js NAPI bindings (installed automatically as a dependency)
  • Vapor Mode compilation is available for Vue 3.6+ (experimental)
  • The plugin supports virtual:vize-styles for importing all compiled CSS as a module
  • .jsx/.tsx Vue components are compiled automatically through the same plugin — see the JSX & TSX guide
  • For experimental rollup / webpack / esbuild / Rspack support, see Experimental Bundler Integrations