# Extension points — vuejs/core

> Canonical page: https://codevetter.com/unpack/vue/extension-points

# Extension points — vuejs/core

Scanned commit 4ab865a848a1da3d10fb674f857e5fff13094644 (2026-09-18). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Extensibility is designed in at four levels. Platform level: `createRenderer(options)` lets anyone build a custom renderer from the same core — `runtime-test` is the in-repo proof. Compile level: `nodeTransforms`/`directiveTransforms` are concatenated after the built-in presets, and compiler-dom/compiler-ssr are themselves just different preset compositions. App level: `app.use`/`app.component`/`app.directive`/`app.mixin` plus `app.config` hooks. Type level: declaration merging into `@vue/runtime-core` interfaces. Adding a package means adding a directory with a `buildOptions` block — `scripts/aliases.js` and `scripts/build.js` discover it automatically.
- `createRenderer<HostNode, HostElement>(options)` is the platform extension point; `createHydrationRenderer` is a separate export specifically so hydration stays tree-shakable, and both delegate to the same `baseCreateRenderer`. — [packages/runtime-core/src/renderer.ts#L318-L347](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-core/src/renderer.ts#L318-L347) [.github/contributing.md#L242](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/.github/contributing.md#L242)
- A renderer is defined entirely by the `RendererOptions` object; runtime-dom composes it as `extend({ patchProp }, nodeOps)`, and `packages/runtime-test` exists as a complete alternative host that renders plain JS objects for assertions. — [packages/runtime-dom/src/index.ts#L71](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-dom/src/index.ts#L71) [packages/runtime-test/package.json](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-test/package.json) [.github/contributing.md#L246](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/.github/contributing.md#L246)
- `baseCompile` appends `options.nodeTransforms` after the built-in preset and merges `options.directiveTransforms` over the built-in `on`/`bind`/`model` map, so third-party compiler plugins plug in without forking the preset. — [packages/compiler-core/src/compile.ts#L108-L134](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-core/src/compile.ts#L108-L134)
- `createStructuralDirectiveTransform` in transform.ts is the factory for writing new structural directives in the style of v-if/v-for, and `traverseNode` is the hook point where each `nodeTransforms[i]` runs and may return an on-exit callback. — [packages/compiler-core/src/transform.ts#L425-L500](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-core/src/transform.ts#L425-L500)
- compiler-dom's `DOMNodeTransforms` and `DOMDirectiveTransforms` are exported arrays/records, explicitly so compiler-ssr can reuse them to generate vnode fallback branches — the comment on `ignoreSideEffectTags` documents why it is kept out of that list. — [packages/compiler-dom/src/index.ts#L27-L55](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-dom/src/index.ts#L27-L55)
- The app-level registries are `context.components`, `context.directives`, `context.provides`, `context.mixins` and the three WeakMap caches (`optionsCache`, `propsCache`, `emitsCache`) created by `createAppContext()`; `app.component`/`app.directive` are thin registrars over the first two with dev-time name validation. — [packages/runtime-core/src/apiCreateApp.ts#L224-L244](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-core/src/apiCreateApp.ts#L224-L244) [packages/runtime-core/src/apiCreateApp.ts#L330-L360](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-core/src/apiCreateApp.ts#L330-L360)
- The plugin interface is `Plugin<Options> = FunctionPlugin | ObjectPlugin` with an `install(app, ...options)` signature; `app.onUnmount(cb)` gives plugins a teardown hook invoked through `callWithAsyncErrorHandling` with `ErrorCodes.APP_UNMOUNT_CLEANUP`. — [packages/runtime-core/src/apiCreateApp.ts#L208-L223](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-core/src/apiCreateApp.ts#L208-L223) [packages/runtime-core/src/apiCreateApp.ts#L419-L445](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-core/src/apiCreateApp.ts#L419-L445)
- `AppConfig` exposes `errorHandler`, `warnHandler`, `globalProperties`, `optionMergeStrategies`, `compilerOptions` and `performance` as the supported runtime customisation surface, with `app.config` itself made non-replaceable via a warning setter. — [packages/runtime-core/src/apiCreateApp.ts#L123-L145](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-core/src/apiCreateApp.ts#L123-L145) [packages/runtime-core/src/apiCreateApp.ts#L283-L293](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-core/src/apiCreateApp.ts#L283-L293)
- TypeScript extension is via declaration merging into named interfaces — runtime-dom itself does this for `RefUnwrapBailTypes`, `AllowedAttrs`, `GlobalComponents` and `GlobalDirectives`, which is the same mechanism router/store libraries use. — [packages/runtime-dom/src/index.ts#L44-L69](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-dom/src/index.ts#L44-L69)
- `HydrationStrategyFactory` is an exported type and the four built-in strategies are plain factory functions, so a userland strategy can be passed to `defineAsyncComponent({ hydrate })` without touching core. — [packages/runtime-core/src/hydrationStrategies.ts#L29-L90](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-core/src/hydrationStrategies.ts#L29-L90) [packages/runtime-core/src/index.ts#L69-L77](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-core/src/index.ts#L69-L77)
- `registerRuntimeCompiler(_compile)` is the documented seam for swapping the runtime compiler, and `isRuntimeOnly()` is derived from whether it has been called — that single boolean drives the dev-only `compilerOptions` deprecation warnings. — [packages/runtime-core/src/component.ts#L979-L997](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-core/src/component.ts#L979-L997) [packages/runtime-dom/src/index.ts#L195-L232](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-dom/src/index.ts#L195-L232)
- `registerTS(loadTS)` and `invalidateTypeCache` are exported from compiler-sfc as the integration seam for bundlers to supply their own TypeScript instance and bust the type cache on HMR, with a hand-written error message when the module cannot be resolved. — [packages/compiler-sfc/src/script/resolveType.ts#L890-L912](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-sfc/src/script/resolveType.ts#L890-L912) [packages/compiler-sfc/src/index.ts#L41-L46](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-sfc/src/index.ts#L41-L46)
- Adding a new workspace package requires no build wiring: `scripts/aliases.js` enumerates `packages/*` at runtime (skipping a `nonSrcPackages` denylist) and `scripts/build.js`/`rollup.config.js` read `packages-private` from disk to decide the package base directory. — [scripts/aliases.js#L13-L36](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/scripts/aliases.js#L13-L36) [scripts/build.js#L153-L166](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/scripts/build.js#L153-L166) [rollup.config.js#L35-L45](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/rollup.config.js#L35-L45)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
