Learn how a Vue application is born and mounted to the DOM.
1The App Instance
Every Vue application begins by creating an app instance with createApp. This instance serves as an isolated environment where you can register global state, routers, and plugins without affecting other Vue apps on the same page.
2The Mount Method
An app instance doesn't render anything until its .mount() method is called. It expects a CSS selector (like #app) or an actual DOM element. Vue will take control of that element's inner HTML.
3<script setup>
<script setup> is a compile-time syntactic sugar for using the Composition API. Variables and imports defined inside this block are directly usable in the template, drastically reducing boilerplate code.
4Step-by-Step Breakdown
Every Vue application starts by creating a new application instance with the createApp function.
You pass your root component (usually App.vue) into createApp. This component is the starting point of your entire component tree.
What function is used to initialize a new Vue 3 application?
- →new Vue
- →createApp
- →initVue
Once the app instance is created, it needs to be injected into a real HTML element on your webpage. We do this using the .mount() method.
In your index.html file, there is usually a single empty <div> with an id. Vue takes over this div and renders everything inside it.
What method is called on the application instance to attach it to an actual HTML element in the DOM?
- →render
- →attach
- →mount
Before mounting the app, you can use the app instance to register global features: plugins (like Vue Router or Pinia), global components, or global directives.
Let's write our very first Vue script block using the Composition API setup attribute.
In Vue 3 Single-File Components, what attribute is added to the <script> tag to enable the Composition API shorthand?
- →setup
- →composition
- →reactive
With <script setup>, any variables or functions you declare are automatically exposed to the <template>. No need to explicitly return them!
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1The Mount Target Should Already Have Meaningful Fallback Content
Because Vue overwrites everything inside the element passed to app.mount(), leaving <div id="app">Loading…</div> in the raw HTML instead of an empty div gives users on slow connections or with JavaScript failures a readable message instead of a blank page during the gap before Vue takes over.
<div id="app">Loading application…</div>SEO Implications
- 1
createApp().mount() Alone Produces No Server-Rendered HTML
createApp/mount is strictly a client-side bootstrap API — calling it produces DOM nodes in the browser, not an HTML string a server can send. Making a Vue app's content indexable requires a separate server-rendering entry point (createSSRApp + renderToString, which is what Nuxt wraps) in addition to this client mount call.
Best Practices
Register Plugins Before Calling mount()
Calls like app.use(router) and app.use(pinia) must happen before app.mount('#app'), because components rendered during mount may immediately rely on injected router or store state; mounting first can produce "inject() called with no matching provider" warnings.
Frequent Bugs
Calling app.mount() before the target element exists in the DOM.
If the script tag runs in the <head> before the <div id="app"> in <body> has been parsed, mount() finds no matching element and fails silently or throws, depending on the build. Place the script tag at the end of <body>, or load it with defer or type="module".
Real-World Examples
Bootstrapping a Vite-Scaffolded App
The default main.js generated by `npm create vue@latest` creates the app, registers the router and Pinia store as plugins, and mounts to #app — this exact sequence is the entry point of nearly every production Vue 3 SPA.
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
createApp(App).use(router).mount('#app');