# Data flow — vuejs/core

> Canonical page: https://codevetter.com/unpack/vue/data-flow

# Data flow — vuejs/core

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

Two largely independent pipelines meet at the component instance. Compile-time: template/SFC source string → tokenizer/parser → AST → transform passes (which mutate the AST and register runtime helpers) → codegen → render-function source. Runtime: props/slots enter via vnodes, reactive state is owned by `Dep` objects linked to `Subscriber`s, changes call `trigger()` which notifies effects, effects are batched into the scheduler queue, and the flush drives `patch()` which writes to the host platform through the injected `RendererOptions`. Output boundaries are exactly three: DOM mutations via `nodeOps`/`patchProp`, an SSR string/stream buffer, and generated JS source text.
- `baseCompile` is the single compile funnel: it resolves `prefixIdentifiers`, calls `baseParse(source, resolvedOptions)` when given a string, composes user `nodeTransforms`/`directiveTransforms` after the base preset, runs `transform(ast, ...)`, and returns `generate(ast, resolvedOptions)`. — [packages/compiler-core/src/compile.ts#L66-L140](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-core/src/compile.ts#L66-L140)
- The base transform preset is order-sensitive and documented as such — transformVBindShorthand, transformOnce, transformIf, transformMemo, transformFor, then (non-browser only) trackVForSlotScopes + transformExpression, then transformSlotOutlet, transformElement, trackSlotScopes, transformText — with directive transforms keyed `on`/`bind`/`model`. — [packages/compiler-core/src/compile.ts#L32-L64](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-core/src/compile.ts#L32-L64)
- compiler-dom layers platform behaviour on top by prepending `ignoreSideEffectTags`, adding `transformStyle` (+ dev-only `transformTransition` and `validateHtmlNesting`), overriding the core `model`/`on` directive transforms, and setting `transformHoist: stringifyStatic` for non-browser builds. — [packages/compiler-dom/src/index.ts#L27-L64](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-dom/src/index.ts#L27-L64)
- compiler-ssr reuses the same `baseParse`/`transform`/`generate` primitives but forces `ssr: true`, `prefixIdentifiers: true`, `cacheHandlers: false`, `hoistStatic: false`, stores the raw options in a `rawOptionsMap` WeakMap keyed by AST root so slot sub-transforms can recover them, and swaps in ssr* node transforms. — [packages/compiler-ssr/src/index.ts#L32-L75](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-ssr/src/index.ts#L32-L75)
- SFC parsing is memoised: `parse.ts` computes a source key and consults `parseCache`, an LRU of max 500 entries created by `createCache()` — which downgrades to a plain `Map` in `__GLOBAL__`/`__ESM_BROWSER__` builds where lru-cache is unavailable. — [packages/compiler-sfc/src/parse.ts#L103-L120](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-sfc/src/parse.ts#L103-L120) [packages/compiler-sfc/src/cache.ts](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-sfc/src/cache.ts)
- `compileScript` merges `<script>` and `<script setup>` through a `ScriptCompileContext`, hard-errors if the two blocks declare different `lang`, returns non-JS/TS blocks untouched, and routes the no-setup case to `processNormalScript(ctx, scopeId)`. — [packages/compiler-sfc/src/compileScript.ts#L168-L215](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-sfc/src/compileScript.ts#L168-L215)
- Type-only props/emits resolution reaches outside the SFC: `resolveFS` in resolveType.ts builds a filesystem host from `ctx.options.fs` or falls back to `ts.sys`, rewriting `.vue.ts` paths back to `.vue`, and walks tsconfig references to resolve imported types across files. — [packages/compiler-sfc/src/script/resolveType.ts#L913-L943](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-sfc/src/script/resolveType.ts#L913-L943) [packages/compiler-sfc/src/script/resolveType.ts#L1099-L1215](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/compiler-sfc/src/script/resolveType.ts#L1099-L1215)
- Reactive reads flow through `track(target, type, key)` in dep.ts which links the active `Subscriber` to a `Dep`; writes flow through `trigger()` which bumps the module-global `globalVersion` counter used to short-circuit stale computed recomputation. — [packages/reactivity/src/dep.ts#L19-L67](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/reactivity/src/dep.ts#L19-L67) [packages/reactivity/src/dep.ts#L262-L310](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/reactivity/src/dep.ts#L262-L310)
- `ReactiveEffect.run()` swaps in `activeSub`/`shouldTrack`, runs `cleanupEffect` + `prepareDeps` before the fn and `cleanupDeps` after, and dev-warns 'Active effect was not restored correctly' if `activeSub` drifted — the double-buffered dep-linking scheme that replaces Vue 3.4's Set-based deps. — [packages/reactivity/src/effect.ts#L162-L200](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/reactivity/src/effect.ts#L162-L200) [packages/reactivity/src/effect.ts#L38-L60](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/reactivity/src/effect.ts#L38-L60)
- Component update jobs are id-ordered: `queueJob` fast-paths an append when the job id is ≥ the tail's id and otherwise binary-inserts via `findInsertionIndex`, ensuring parents flush before children; `queueFlush` schedules `flushJobs` on a resolved promise microtask. — [packages/runtime-core/src/scheduler.ts#L78-L123](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-core/src/scheduler.ts#L78-L123)
- `flushJobs` iterates the queue with `callWithErrorHandling`, clears QUEUED flags in a `finally` block even after a throw, then calls `flushPostFlushCbs` and recurses if either queue refilled during the flush. — [packages/runtime-core/src/scheduler.ts#L221-L280](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-core/src/scheduler.ts#L221-L280)
- All DOM writes funnel through the `rendererOptions` object = `extend({ patchProp }, nodeOps)` passed to `createRenderer`; inside the renderer they are reachable only as the `o` field of the `internals` object shared with Teleport, Suspense and KeepAlive. — [packages/runtime-dom/src/index.ts#L71-L85](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-dom/src/index.ts#L71-L85) [packages/runtime-core/src/renderer.ts#L2478-L2492](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/runtime-core/src/renderer.ts#L2478-L2492)
- SSR output is a nested `SSRBuffer` of strings and promises; `renderToString` awaits `renderComponentVNode(vnode)` then `unrollBuffer`, which takes a fully synchronous path (`unrollBufferSync`) when `buffer.hasAsync` is false and otherwise resolves promises in place before concatenating. — [packages/server-renderer/src/renderToString.ts#L14-L95](https://github.com/vuejs/core/blob/4ab865a848a1da3d10fb674f857e5fff13094644/packages/server-renderer/src/renderToString.ts#L14-L95)

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)
