Unraveling Vue 3 Initialization: From createApp to VNode Rendering
This article walks through Vue 3's initialization process, explaining what createApp(App).mount('#app') does, how the runtime‑dom and runtime‑core modules create and render VNodes, and how patch, shapeFlags, and patchFlags drive efficient DOM updates.
Goal
Understand what
createApp(App).mount("#app")actually does and explore Vue 3.0's initialization rendering process.
What You’ll Gain
Insight into Vue 3.0's initialization flow.
Direction for reading Vue 3.0 source code.
Getting Started
Clone the
vue-nextrepository, enable source maps in
package.json, and run
yarn dev. This builds
vue.global.jsand its sourcemap, allowing step‑by‑step debugging of the call stack.
Runtime‑dom
The
createApp()function originates from
runtime-dom. It registers a
mountmethod on the app instance, enabling a basic demo to run without errors.
<code>const app = {data(){return {counter:1}}}
Vue.createApp(app).mount("#app")</code>Key functions include
ensureRenderer(which obtains a renderer via
createRendererfrom
runtime-core) and the platform‑specific
nodeOpsthat wrap DOM APIs.
Runtime‑core
Inside
runtime-core,
baseCreateRenderer(≈2000 lines) builds the core rendering logic.
createAppis created by
createAppAPI, ultimately returning an app object with a
mountmethod.
First Render: .mount("#app")
The demo uses the classic API. The
dom‑mountimplementation prepares the container, extracts the template if needed, clears the content, and calls the core
mountfunction.
<code>const { mount } = app;
app.mount = (containerOrSelector) => {
const container = normalizeContainer(containerOrSelector);
if (!container) return;
const component = app._component;
if (!isFunction(component) && !component.render && !component.template) {
component.template = container.innerHTML;
}
container.innerHTML = "";
const proxy = mount(container);
container.removeAttribute("v-cloak");
return proxy;
};</code>The core
mountcreates a root VNode, then calls
render, which delegates to
patch.
Creating the Root VNode
The VNode is initialized with properties such as
type,
shapeFlag,
patchFlag, etc.
shapeFlaguses bitwise enums (e.g., ELEMENT=1, STATEFUL_COMPONENT=4) to identify node kinds.
<code>export const enum ShapeFlags {
ELEMENT = 1,
FUNCTIONAL_COMPONENT = 1 << 1,
STATEFUL_COMPONENT = 1 << 2,
TEXT_CHILDREN = 1 << 3,
ARRAY_CHILDREN = 1 << 4,
// ... other flags
}</code>Patch flags (e.g., TEXT=1, CLASS=1<<1) mark dynamic parts for optimized diffing.
<code>export const enum PatchFlags {
TEXT = 1,
CLASS = 1 << 1,
STYLE = 1 << 2,
PROPS = 1 << 3,
FULL_PROPS = 1 << 4,
// ... other flags
}</code>Patch Process
patchexamines a VNode's
typeand
shapeFlagto dispatch to specific processors (e.g.,
processElement,
processComponent,
processFragment,
processText, etc.). It handles mounting when no previous VNode exists and updating otherwise.
<code>if (n1 && !isSameVNodeType(n1, n2)) {
// unmount old tree
n1 = null;
}
const { type, shapeFlag } = n2;
switch (type) {
case Text:
processText(n1, n2, container, anchor);
break;
// ... other cases
default:
if (shapeFlag & ShapeFlags.ELEMENT) {
processElement(...);
} else if (shapeFlag & ShapeFlags.COMPONENT) {
processComponent(...);
}
}
</code>Fragment, Teleport, and Suspense are new Vue 3 components, each identified by distinct
shapeFlagvalues.
Component Mounting
During mounting, Vue creates a component internal instance, initializes props and slots, sets up reactivity, and compiles the template into a render function. The render function returns a VNode tree, which is then patched into the DOM.
<code>function componentEffect() {
if (!instance.isMounted) {
const subTree = (instance.subTree = renderComponentRoot(instance));
patch(null, subTree, container);
instance.isMounted = true;
} else {
// update path
}
}
</code>Reactivity is driven by
effect, which tracks dependencies during the render and triggers updates when reactive state changes.
Summary
The article dissects Vue 3’s bootstrapping: cloning the source, enabling source maps, tracing
createAppthrough
runtime-domand
runtime-core, understanding VNode creation, the role of
shapeFlagand
patchFlag, and how the patch algorithm efficiently mounts and updates the DOM.
WeDoctor Frontend Technology
Official WeDoctor Group frontend public account, sharing original tech articles, events, job postings, and occasional daily updates from our tech team.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.