Open-Source Wikis

/

Vue.js

/

Packages

/

compiler-dom

vuejs/core

compiler-dom

Active contributors: Evan You, daiwei, edison

Purpose

@vue/compiler-dom is the browser-flavored template compiler. It is a thin layer on top of @vue/compiler-core that:

  • Configures HTML-aware parser options (entity decoding, void elements, raw text elements).
  • Adds DOM-only nodeTransforms (style attribute parsing, transition validation, HTML nesting validation).
  • Overrides v-model and v-on to produce DOM-aware code (vModelText vs vModelCheckbox etc., event modifier wrappers).
  • Adds DOM-only directives (v-html, v-text, v-show, v-cloak).

The package is small (~1,400 lines, 16 files). It is what the runtime-compiler full build (vue.global.js, vue.esm-browser.js) bundles, and what compiler-sfc invokes for the <template> block.

Directory layout

packages/compiler-dom/src/
├── index.ts              # compile, parse, DOMNodeTransforms, DOMDirectiveTransforms
├── parserOptions.ts      # HTML-specific parser options
├── runtimeHelpers.ts     # additional symbolic ids (V_MODEL_TEXT, V_SHOW, …)
├── errors.ts             # DOM-specific error codes
├── decodeHtmlBrowser.ts  # HTML entity decoder (browser uses DOMParser; node uses entities)
├── htmlNesting.ts        # the HTML "what can nest in what" tables
└── transforms/
    ├── transformStyle.ts          # parses inline `style="..."` strings into objects
    ├── vHtml.ts                   # v-html → innerHTML
    ├── vText.ts                   # v-text → textContent
    ├── vModel.ts                  # rewrites v-model based on host element
    ├── vOn.ts                     # event modifier flags + DOM event handling
    ├── vShow.ts                   # v-show → withDirectives + vShow
    ├── Transition.ts              # warns on multi-children <Transition>
    ├── stringifyStatic.ts         # large hoisted static node → string template
    ├── ignoreSideEffectTags.ts    # warn on <script>/<style> in template
    └── validateHtmlNesting.ts     # warn for invalid nesting (e.g., <p><div>)

How it slots in

// packages/compiler-dom/src/index.ts
export const DOMNodeTransforms: NodeTransform[] = [
  transformStyle,
  ...(__DEV__ ? [transformTransition, validateHtmlNesting] : []),
];

export const DOMDirectiveTransforms: Record<string, DirectiveTransform> = {
  cloak: noopDirectiveTransform,
  html: transformVHtml,
  text: transformVText,
  model: transformModel, // override compiler-core
  on: transformOn, // override compiler-core
  show: transformShow,
};

export function compile(src, options = {}) {
  return baseCompile(
    src,
    extend({}, parserOptions, options, {
      nodeTransforms: [
        ignoreSideEffectTags,
        ...DOMNodeTransforms,
        ...(options.nodeTransforms || []),
      ],
      directiveTransforms: extend(
        {},
        DOMDirectiveTransforms,
        options.directiveTransforms || {}
      ),
      transformHoist: __BROWSER__ ? null : stringifyStatic,
    })
  );
}

The package also exports the parserOptions object so compiler-ssr can reuse it without inheriting the DOM-only transforms.

Why stringifyStatic

stringifyStatic (packages/compiler-dom/src/transforms/stringifyStatic.ts) is enabled only outside the browser build (!__BROWSER__). When cacheStatic decides to hoist a large fully-static subtree, this hoist transform converts the resulting vnode to a createStaticVNode("<div>…</div>", count) call: a single string set via innerHTML that creates many DOM nodes at once. This is much cheaper than constructing N vnodes during hydration.

It is browser-build-disabled because in the browser the compiler runs at runtime; emitting raw HTML strings would defeat the whole point of vnode equality optimizations and could clash with the user's templating environment.

Key abstractions

Symbol File Description
compile, parse packages/compiler-dom/src/index.ts DOM-flavored entries that wrap baseCompile/baseParse.
parserOptions packages/compiler-dom/src/parserOptions.ts HTML-specific options: isPreTag, isVoidTag, getNamespace, decodeEntities.
transformStyle packages/compiler-dom/src/transforms/transformStyle.ts Parses static style="…" strings into { key: val } objects so they can be diffed without reparsing every patch.
transformModel packages/compiler-dom/src/transforms/vModel.ts Picks the right runtime vModelXxx directive based on <input type>, <textarea>, <select>.
transformOn packages/compiler-dom/src/transforms/vOn.ts Emits _withModifiers/_withKeys wrappers for v-on.stop.prevent.self.once.passive.capture and key filters.
validateHtmlNesting packages/compiler-dom/src/transforms/validateHtmlNesting.ts Dev-only check using the table in htmlNesting.ts to catch obvious mistakes like <p><div>.
DOMErrorCodes, DOMErrorMessages packages/compiler-dom/src/errors.ts DOM-specific error codes; merged with core codes by compiler-sfc.

Integration points

  • Runs inside vue (full builds) for runtime template compilation.
  • Runs inside compiler-sfc.compileTemplate for SFC templates.
  • Imported by compiler-ssr, which reuses parserOptions, transformBind, transformOn, transformStyle, etc., but installs its own element/component transforms.

Entry points for modification

  • New DOM directive? Add a transform in transforms/, register in DOMDirectiveTransforms.
  • New element-level optimization? Add a NodeTransform and register in DOMNodeTransforms.
  • HTML parsing edge case? parserOptions.ts is the file; the underlying state machine lives in compiler-core's tokenizer.ts.
  • Nesting rule change? Update the table in htmlNesting.ts.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

compiler-dom – Vue.js wiki | Factory