Vize

Vite Plugin

⚠️ Work in Progress: Vize is under active development and is not yet ready for production use. Test thoroughly before adopting 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({});

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"). 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

// vite.config.js
import { defineConfig } from "vite";
import vize from "@vizejs/vite-plugin";

export default defineConfig({
  plugins: [vize()],
});

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"]
  }
}

For Vite+ projects, keep options in the integration helper's compiler field in vite.config.ts. For ordinary Vite, use direct vize({ ... }) options. Shared standalone config is optional when CLI or LSP commands also need those settings.

Optional standalone shared config

When CLI or LSP commands need the same settings, use defineConfig from vize and a vize.config.* file. Install vize directly when importing that helper. The standalone configuration reference preserves file discovery, TypeScript/JSON/PKL examples, and scoped settings. Vite+ integration tasks use the helper in vite.config.ts.

Compiler Options

Direct options passed to vize() override vize.config.*. The full precedence is direct plugin options, then inline config, then vize.config.*, then defaults.

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 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 compiler.ssr or vize({ ssr }) Force SSR compilation when Vite's SSR build flag is not enough.
vapor compiler.vapor or vize({ vapor }) Compile templates through the Vapor backend.
jsxMode compiler.jsxMode or vize({ jsxMode }) Default output backend ("vdom" / "vapor") for .jsx/.tsx components. Per-component "use vue:*" directives override it.
customRenderer compiler.customRenderer or vize({ customRenderer }) Treat lowercase non-HTML tags as custom renderer elements. Does not match PascalCase tags such as <TresMesh>.
customElements compiler.customElements or vize({ customElements }) Tag patterns compiled as custom elements instead of Vue components. Use ["Tres*"] for TresJS PascalCase renderer tags.
templateSyntax compiler.templateSyntax or vize({ templateSyntax }) Choose "standard", "strict", or "quirks" template syntax handling.
whitespace 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.
template.compilerOptions.comments 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 top-level experimentals or vize({ experimentals }) Fully opt-in Vue RFC and backend experiments. Missing keys, false, and null are off.
include vite.include or vize({ include }) Files that the plugin should compile.
exclude vite.exclude or vize({ exclude }) Files that the plugin should ignore.
scanPatterns vite.scanPatterns or vize({ scanPatterns }) Glob patterns used for startup pre-compilation.
ignorePatterns 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
  → Armature (Parser)          — Tokenizes and parses the SFC structure
  → Croquis (Semantic Analysis) — Analyzes template expressions and bindings
  → Atelier (Compilation)       — Generates optimized JavaScript output
  → Vitrine (NAPI Binding)      — Delivers the result to Node.js
  → 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 First-class (vize_atelier_vapor)
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.

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 via vize_atelier_vapor (Vue 3.6+)
  • VDOM compilation uses vize_atelier_dom
  • 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