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-next repository, enable source maps in package.json, and run yarn dev. This builds vue.global.js and its sourcemap, allowing step‑by‑step debugging of the call stack.
Runtime‑dom
The createApp() function originates from runtime-dom. It registers a mount method on the app instance, enabling a basic demo to run without errors.
const app = {data(){return {counter:1}}}
Vue.createApp(app).mount("#app")Key functions include ensureRenderer (which obtains a renderer via createRenderer from runtime-core) and the platform‑specific nodeOps that wrap DOM APIs.
Runtime‑core
Inside runtime-core, baseCreateRenderer (≈2000 lines) builds the core rendering logic. createApp is created by createAppAPI, ultimately returning an app object with a mount method.
First Render: .mount("#app")
The demo uses the classic API. The dom‑mount implementation prepares the container, extracts the template if needed, clears the content, and calls the core mount function.
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;
};The core mount creates 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. shapeFlag uses bitwise enums (e.g., ELEMENT=1, STATEFUL_COMPONENT=4) to identify node kinds.
export const enum ShapeFlags {
ELEMENT = 1,
FUNCTIONAL_COMPONENT = 1 << 1,
STATEFUL_COMPONENT = 1 << 2,
TEXT_CHILDREN = 1 << 3,
ARRAY_CHILDREN = 1 << 4,
// ... other flags
}Patch flags (e.g., TEXT=1, CLASS=1<<1) mark dynamic parts for optimized diffing.
export const enum PatchFlags {
TEXT = 1,
CLASS = 1 << 1,
STYLE = 1 << 2,
PROPS = 1 << 3,
FULL_PROPS = 1 << 4,
// ... other flags
}Patch Process
patchexamines a VNode's type and shapeFlag to dispatch to specific processors (e.g., processElement, processComponent, processFragment, processText, etc.). It handles mounting when no previous VNode exists and updating otherwise.
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(...);
}
}Fragment, Teleport, and Suspense are new Vue 3 components, each identified by distinct shapeFlag values.
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.
function componentEffect() {
if (!instance.isMounted) {
const subTree = (instance.subTree = renderComponentRoot(instance));
patch(null, subTree, container);
instance.isMounted = true;
} else {
// update path
}
}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 createApp through runtime-dom and runtime-core, understanding VNode creation, the role of shapeFlag and patchFlag, and how the patch algorithm efficiently mounts and updates the DOM.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
