Experimentals Reference
This page is the dense reference for Experimentals and Vue RFC Experimental Details. Use it when you need to know which entry point resolves a flag, what proof belongs with a change, and which low-level API fields are already final booleans.
Entry Points
Use the highest-level entry point that still owns the decision. Project config is for tools that load Vize config, direct plugin options are for one Vite plugin instance, and native compiler fields are only for integrations that have already resolved project policy.
| Entry point | Accepted shape | Who resolves it | Notes |
|---|---|---|---|
vize.config.* |
experimentals: { ... } switch values |
config loader | Shared default for npm commands, vize check, LSP sessions, and Vite plugin instances that load project config |
vize({ experimentals }) |
the same switch values | Vite plugin option resolver | Direct values win over shared config; false and null are per-plugin opt-outs |
vize({ vapor }), vize({ jsxMode }), compiler.vapor, compiler.jsxMode |
stable compiler options | compiler option resolver | These stable choices win over experimentals.vapor and experimentals.jsxVapor fallback routing |
compile, compileVapor, parseTemplate |
experimental* boolean fields on CompilerOptions |
caller | No aliases, no {} switch object, and no shared-config precedence |
compileSfc, compileSfcBatch, compileSfcBatchWithResults |
experimental* boolean fields on SFC/batch options |
caller | Use for native SFC or WASM integrations after config resolution |
vize check and LSP/type-check project APIs |
project experimentals plus resolved type-checker flags |
config loader and project session | strictSlotChildren produces virtual TypeScript checks here, not runtime codegen |
Flag Contracts
| Flag | Enable when | Smallest useful proof | What remains outside the flag |
|---|---|---|---|
patternedTemplate |
A project intentionally wants RFC #823 v-match / v-when branches in authored templates |
Compile one flagged component with a direct v-match child and one flag-off component that reports experimentals.patternedTemplate |
Content Mapper routing, complete editor navigation coverage, and or-pattern bindings |
inTagComment |
Tooling needs line-local annotations inside an opening tag, such as @vue-expect-error near the affected prop |
Parse one tagged component and assert the comment is preserved in root.comments while output code stays unchanged |
Browser in-DOM templates, runtime comments, and the normal comments compiler option |
selfComponent |
A recursive SFC wants RFC #833 self-reference without relying on name or filename inference alone |
Compile <Self /> with componentName or SFC metadata and verify a local import named Self is not the target |
JSX, render functions, and lowercase <self> |
strictSlotChildren |
A library or application exposes RFC #734 typed slot-child contracts and wants vize check or LSP diagnostics |
Type-check one valid default/named slot tuple and one invalid child that TypeScript rejects | Runtime rendering, open any slot contracts, and built-in/dynamic component child typing |
serverScript |
A host integration owns and tests a server-script compiler experiment | Assert the native experimentalServerScript boolean is forwarded only when the switch is enabled |
Public server-script syntax semantics until a host documents them |
vapor |
A project is trying SFC Vapor before promoting it to stable compiler.vapor |
Verify experimentals.vapor: true selects Vapor only when compiler.vapor and direct vize({ vapor }) are unset |
Stable project-wide Vapor policy |
jsxVapor |
A project is trying JSX/TSX Vapor before promoting it to stable compiler.jsxMode |
Verify experimentals.jsxVapor: true defaults JSX output to Vapor only when jsxMode is unset |
Per-file "use vue:*" directives and stable JSX backend policy |
RFC #831 has the same opt-in shape as the other RFC
flags, but its behavior is parser/tooling-only: it keeps // annotations near attributes and does
not emit runtime comments.
Direct API Fields
Most applications should configure experimentals. Lower-level integrations that already perform
their own config resolution can pass native compiler fields directly:
import {
compile,
compileSfc,
compileSfcBatchWithResults,
compileVapor,
parseTemplate,
} from "@vizejs/native";
compile(templateSource, {
experimentalInTagComments: true,
experimentalPatternedTemplate: true,
experimentalSelfComponent: true,
experimentalServerScript: true,
componentName: "TreeNode",
});
compileVapor(templateSource, {
experimentalInTagComments: true,
experimentalPatternedTemplate: true,
experimentalSelfComponent: true,
componentName: "TreeNode",
});
parseTemplate(templateSource, {
experimentalInTagComments: true,
});
compileSfc(sfcSource, {
filename: "TreeNode.vue",
experimentalInTagComments: true,
experimentalPatternedTemplate: true,
experimentalSelfComponent: true,
experimentalStrictSlotChildren: true,
experimentalServerScript: true,
});
compileSfcBatchWithResults(files, {
experimentalInTagComments: true,
experimentalPatternedTemplate: true,
experimentalSelfComponent: true,
experimentalStrictSlotChildren: true,
experimentalServerScript: true,
});
These fields are already resolved booleans. They do not understand aliases, {} switch objects, or
shared-config precedence. Use them only at integration boundaries where the caller owns those rules.
Config Recipes
Enable the smallest flag set that proves the intended behavior. Do not group unrelated RFC switches
behind one project toggle, and do not promote an experimental flag to default-on in shared config
until the feature has moved to a stable compiler or tool option.
One RFC proposal in shared config:
import { defineConfig } from "vize";
export default defineConfig({
experimentals: {
inTagComment: true,
},
});
Temporary per-plugin opt-out while shared config stays enabled:
import { defineConfig } from "vite";
import vize from "@vizejs/vite-plugin";
export default defineConfig({
plugins: [
vize({
experimentals: {
inTagComment: false,
patternedTemplate: null,
},
}),
],
});
Low-level integration after config resolution:
compile(templateSource, {
experimentalInTagComments: resolvedExperimentals.inTagComments,
experimentalPatternedTemplate: resolvedExperimentals.patternedTemplate,
});
In native API calls, never pass compatibility aliases such as intagComment or switch objects such
as {}. Resolve them before calling the compiler.
Failure Examples
patternedTemplate stays fail-closed when structure is wrong:
<template v-match="status"></template>
<template v-match="status">
<p v-when:ready="'ready'">Ready</p>
<p v-when.once="'ready'">Ready again</p>
</template>
inTagComment is not a second expression grammar for attributes:
<template>
<LegacySelect :label="'// this is an attribute value, not an in-tag comment'" />
<LegacySelect
:// not a directive argument comment
selected-id="abc"
/>
</template>
Slot Cardinality
RFC #734 return shapes are preserved as TypeScript cardinality contracts:
| Slot return contract | Meaning in Vize virtual TS |
|---|---|
() => HTMLInputElement |
one input child, accepting the single-child shorthand |
() => HTMLInputElement[] |
zero or more input children |
() => [HTMLInputElement, HTMLInputElement] |
exactly two input children in tuple order |
() => (typeof TabItem)[] |
zero or more TabItem component children |
() => [typeof TabItem, HTMLButtonElement] |
one TabItem child followed by one button child |
Implementation Coverage
| Concern | Required proof before changing docs |
|---|---|
| Default-off behavior | A flag-off parse, compile, check, or LSP path reports or preserves the documented off behavior |
| Config resolution | Shared config, direct Vite plugin values, aliases, false, null, and {} are covered separately from native booleans |
| Native template APIs | compile, compileVapor, and parseTemplate accept only the documented experimental* boolean fields |
| Native SFC APIs | compileSfc, compileSfcBatch, and compileSfcBatchWithResults forward the same booleans per file or batch |
| Type-checking APIs | strictSlotChildren is proven through virtual TypeScript diagnostics, not through runtime output snapshots |
| Boundary tests | Deferred RFC behavior has a negative assertion or documented absence, so users do not infer support from nearby syntax |
Release Safety Checklist
Before release notes claim an experimental surface, check all of these against the shipped entry point:
- default-off behavior is verified for the public config key and the direct native field
- aliases are documented as compatibility inputs, not as recommended names
- direct Vite plugin values can enable and explicitly opt out of shared config
false,null,true, and{}keep the documented switch semantics- backend fallback flags such as
vaporandjsxVaporlose to stablecompileroptions - RFC examples include both an enabled example and a flag-off or invalid-shape diagnostic example
- boundaries name deferred behavior, such as patterned-template editor navigation or strict slot support for dynamic components