Production build file selection for Vue without build tools
When deploying Vue without a build tool from a CDN or self-hosted script, use the production build files that end in `.prod.js`. For the global build (accessing via the Vue global), use `vue.global.prod.js`. For the ESM build (accessing via native ESM imports), use `vue.esm-browser.prod.js`. Production builds are pre-minified with all development-only code branches removed.
Vue production setup with build tools configuration
Projects using `create-vue` (based on Vite) or Vue CLI (based on webpack) are pre-configured for production builds. For custom setups, three things must be ensured: (1) `vue` resolves to `vue.runtime.esm-bundler.js`, (2) the compile time feature flags are properly configured, and (3) `process.env.NODE_ENV` is replaced with `"production"` during build.
App-level error handler for tracking runtime errors
The app-level error handler can be used to report errors to tracking services. Example: `app.config.errorHandler = (err, instance, info) => { // report error to tracking services }`. Services such as Sentry and Bugsnag provide official integrations for Vue.
Development vs production features in Vue
Vue provides several features during development that become useless in production: warnings for common errors and pitfalls, props and events validation, reactivity debugging hooks, and devtools integration. These features and their warning checks add a small performance overhead. When deploying to production, all unused development-only code branches should be removed for smaller payload size and better performance.
Vue Web Components for embedding
Vue can be used to build standard Web Components that can be embedded in any HTML page regardless of how they are rendered. Web Components built with Vue can be embedded in legacy applications, static HTML, or applications built with other frameworks.
Single-Page Application (SPA) use case
Single-Page Applications are best for applications requiring rich interactivity, deep session depth, and non-trivial stateful logic on the frontend. Vue controls the entire page, handles data updates and navigation without reloading the page. Vue provides core libraries, comprehensive tooling support, client-side router, blazing fast build tool chain, IDE support, browser devtools, TypeScript integrations, and testing utilities for building modern SPAs.
SPA backend architecture
SPAs typically require the backend to expose API endpoints. Vue can also be paired with solutions like Inertia.js to get SPA benefits while retaining a server-centric development model.
Server-Side Rendering (SSR) improves Core Web Vitals
Pure client-side SPAs are problematic for SEO-sensitive apps because the browser receives a largely empty HTML page and must wait for JavaScript to load before rendering. Vue provides first-class APIs to render a Vue app into HTML strings on the server. The server sends back already-rendered HTML for immediate content visibility while JavaScript downloads. Vue then hydrates the application on the client side to make it interactive. This greatly improves Core Web Vital metrics such as Largest Contentful Paint (LCP).
Static-Site Generation (SSG) / JAMStack approach
Server-side rendering can be done ahead of time if required data is static. The entire application can be pre-rendered into HTML and served as static files, improving site performance and making deployment simpler without dynamic page rendering on each request. Vue can still hydrate such applications to provide rich interactivity on the client. This technique is called Static-Site Generation (SSG) or JAMStack.
Single-page SSG vs Multi-page SSG
Both flavors of SSG pre-render the site into static HTML with different trade-offs. Single-page SSG hydrates the initial page into an SPA, requiring more upfront JavaScript payload and hydration cost, but subsequent navigations are faster since only partial page updates are needed. Multi-page SSG loads a new page on every navigation with minimal or no JavaScript required if the page needs no interaction, but each navigation requires a full page reload. Single-page SSGs are better for non-trivial interactivity, deep session lengths, or persisted state across navigations. Multi-page SSG is better otherwise.
VitePress static-site generator
The Vue team maintains a static-site generator called VitePress which powers the Vue documentation website and supports both single-page and multi-page SSG flavors.
Partial hydration in multi-page SSG
Some multi-page SSG frameworks such as Astro support partial hydration, which allows Vue components to create interactive islands inside static HTML.
Vue beyond the web platforms
Vue can be used to build desktop apps with Electron or Wails, mobile apps with Ionic Vue, desktop and mobile apps from the same codebase with Quasar or Tauri, 3D WebGL experiences with TresJS, and custom renderers using Vue's Custom Renderer API such as terminal-based renderers.
Standalone Script usage without build step
Vue can be used as a standalone script file with no build step required. This is useful when a backend framework already renders most HTML or when frontend logic is not complex enough to justify a build step. Vue can be thought of as a more declarative replacement for jQuery in such cases.
Petite-vue no longer maintained
Petite-vue was a previously provided distribution specifically optimized for progressively enhancing existing HTML. It is no longer actively maintained, with the last version published at Vue 3.2.27.
Build Vue production application with yarn
To create a production-ready build, run: yarn build. This generates an optimized build in the ./dist directory.
Use development build for CDN development
When using Vue from a CDN during development, you are using the development build. For production use, consult the Production Deployment Guide to ensure proper setup.
Build Vue production application with pnpm
To create a production-ready build, run: pnpm run build. This generates an optimized build in the ./dist directory.
Build Vue production application with bun
To create a production-ready build, run: bun run build. This generates an optimized build in the ./dist directory.
Suppressing hydration mismatches in Vue 3.5+
In Vue 3.5 and later, you can selectively suppress inevitable hydration mismatches using the data-allow-mismatch attribute.
Vue SSR definition and isomorphic apps
Server-Side Rendering (SSR) in Vue.js renders the same components into HTML strings on the server, sends them to the browser, and then hydrates the static markup into a fully interactive app on the client. A server-rendered Vue.js app is also called isomorphic or universal because the majority of the app's code runs on both the server and the client.
SSR advantages: faster time-to-content
Server-rendered markup doesn't need to wait for all JavaScript to be downloaded and executed before being displayed, so users see a fully-rendered page sooner. Data fetching is done on the server-side for the initial visit, which typically has a faster connection to the database than the client. This generally results in improved Core Web Vitals metrics and better user experience, and is critical for applications where time-to-content affects conversion rate.
SSR advantages: unified mental model and better SEO
SSR allows you to use the same language and declarative, component-oriented mental model for developing your entire app instead of switching between a backend templating system and frontend framework. Search engine crawlers see the fully rendered page directly, improving SEO. However, if your app starts with a loading spinner then fetches content via Ajax, crawlers will not wait for content to finish loading.
SSR trade-offs and constraints
SSR has several trade-offs: development constraints (browser-specific code only works in certain lifecycle hooks, some libraries need special treatment), more complex build setup and deployment requirements (needs a Node.js server environment), and higher server-side load (rendering full apps in Node.js is CPU-intensive, requiring caching strategies for high traffic).
SSG vs SSR comparison
Static Site Generation (SSG), also called pre-rendering, renders pages once during build time for static data and serves them as static HTML files. SSG retains the same performance characteristics and time-to-content of SSR apps but is cheaper and easier to deploy because output is static. SSG can only be applied to pages with static data known at build time. Every time data changes, a new deployment is needed. SSG is better for pages with static content like documentation, blogs, and marketing pages.
Vue SSR basic example using createSSRApp and renderToString
Example code showing Vue SSR with createSSRApp and renderToString:
import { createSSRApp } from 'vue'; import { renderToString } from 'vue/server-renderer'; const app = createSSRApp({ data: () => ({ count: 1 }), template: `<button @click="count++">{{ count }}</button>` }); renderToString(app).then((html) => { console.log(html) }); The renderToString() function takes a Vue app instance and returns a Promise that resolves to the rendered HTML of the app.
Client hydration for SSR apps
Hydration is the step where Vue creates the same Vue application that ran on the server on the client side, matches each component to the DOM nodes it should control, and attaches DOM event listeners. To mount an app in hydration mode, use createSSRApp() instead of createApp(). When an SSR app mounts on the client, it assumes the HTML was pre-rendered and performs hydration instead of mounting new DOM nodes.
Reactivity disabled on server for SSR
During SSR, each request URL maps to a desired state of the application. Since there is no user interaction and no DOM updates during server rendering, reactivity is unnecessary on the server and is disabled by default for better performance.
SSR lifecycle hooks behavior
During SSR, only beforeCreate and created hooks are called. Hooks such as mounted, updated, beforeUnmount, and unmounted will NOT be called during SSR and will only execute on the client. Avoid code with side effects that need cleanup in beforeCreate and created, such as setInterval timers, since unmount hooks are never called during SSR. Move side-effect code into mounted instead to ensure timers are properly cleaned up on the client.
Universal code cannot assume platform-specific APIs
Code shared between server and client (universal code) cannot assume access to platform-specific APIs. Directly using browser-only globals like window or document will throw errors when executed in Node.js, and vice-versa. For tasks shared between server and client with different platform APIs, wrap implementations inside a universal API or use libraries like node-fetch that provide the same API on both server and client. For browser-only APIs, lazily access them inside client-only lifecycle hooks like mounted.
Cross-request state pollution in SSR
In SSR, application modules are typically initialized only once when the server boots up, and the same module instances are reused across multiple server requests. If shared singleton state objects are mutated with data specific to one user, it can leak to requests from other users. This is called cross-request state pollution. The solution is to create a new instance of the entire application, including router and stores, on each request, then provide shared state using app-level provide and inject in components that need it rather than direct imports.
Hydration mismatch causes and solutions
Hydration mismatch occurs when the DOM structure of pre-rendered HTML doesn't match the client-side app's expected output. Common causes: (1) Invalid HTML nesting that browsers correct (e.g., <div> inside <p>); (2) Randomly generated values during render - use v-if + onMounted or seeded random generators; (3) Different time zones between server and client - perform local time conversion client-only. Vue automatically attempts recovery by adjusting pre-rendered DOM, but this causes rendering performance loss. Eliminate mismatches during development.
Custom directives getSSRProps hook for SSR
Most custom directives are ignored during SSR because they involve direct DOM manipulation. To specify how a custom directive should be rendered on the server, use the getSSRProps directive hook. This hook receives the directive binding and returns an object with props to be rendered. Example: getSSRProps(binding) { return { id: binding.value } }
Teleports with SSR require special handling
Teleports require special handling during SSR. Teleported content will not be part of the main rendered string. An easier solution is to conditionally render the Teleport on mount. If hydrating teleported content is needed, access teleported content through the teleports property of the ssr context object: const ctx = {}; const html = await renderToString(app, ctx); console.log(ctx.teleports); Inject teleport markup into the correct location in the final page HTML. Avoid targeting body when using Teleports and SSR - instead use a dedicated container like <div id="teleported"></div>.
Laravel Vite plugin for Vue integration
If using Vue with Laravel, the framework ships an official Vite plugin that handles asset bundling and hot-module replacement out of the box. Documentation: https://laravel.com/docs/vite
Vite backend integration guide
For backend frameworks other than Laravel, refer to Vite's Backend Integration guide (https://vite.dev/guide/backend-integration.html) to wire up Vue integration manually.
Vite is the recommended build tool for Vue
Vite is a lightweight and fast build tool with first-class Vue SFC support. It is created by Evan You, who is also the author of Vue. The command to get started is: npm create vue@latest (npm), pnpm create vue@latest (pnpm), yarn create vue@latest (Yarn Modern v2+) or yarn dlx create-vue@latest (Yarn ^v4.11), or bun create vue@latest (bun).
create-vue is the official Vue project scaffolding tool
create-vue is the official Vue project scaffolding tool that is installed and executed when running npm create vue@latest or equivalent commands.
Vue CLI is in maintenance mode
Vue CLI is the official webpack-based toolchain for Vue. It is now in maintenance mode. Vite is recommended for starting new projects unless you rely on specific webpack-only features, as Vite provides superior developer experience in most cases.
Recommended IDE setup for Vue
The recommended IDE setup is VS Code with the Vue - Official extension. The extension provides syntax highlighting, TypeScript support, and intellisense for template expressions and component props.
Prettier supports Vue SFC formatting
Prettier provides built-in Vue SFC formatting support as an alternative to the Vue - Official extension.
Vue - Official replaces Vetur
Vue - Official is the new official VS Code extension for Vue 3 and replaces Vetur. If Vetur is currently installed, it should be disabled in Vue 3 projects.
WebStorm built-in Vue SFC support
WebStorm provides great built-in support for Vue SFCs.
LSP support for Vue in other IDEs
IDEs that support the Language Service Protocol (LSP) can leverage Volar's core functionalities. Support includes: Sublime Text via LSP-Volar (https://github.com/sublimelsp/LSP-volar), vim/Neovim via coc-volar (https://github.com/yaegassy/coc-volar), and emacs via lsp-mode (https://emacs-lsp.github.io/lsp-mode/page/lsp-volar/).
Vue browser devtools capabilities
The Vue browser devtools extension allows you to explore a Vue app's component tree, inspect the state of individual components, track state management events, and profile performance. It is available as a Chrome Extension, Vite Plugin, and Standalone Electron app at https://devtools.vuejs.org/.
vue-tsc for TypeScript checking
vue-tsc can be used for performing type checking from the command line or for generating d.ts files for SFCs. It is available at https://github.com/vuejs/language-tools/tree/master/packages/tsc.
eslint-plugin-vue for Vue linting
The Vue team maintains eslint-plugin-vue, an ESLint plugin that supports SFC-specific linting rules.
Recommended linting setup for Vite projects
For Vite-based builds, the recommended linting setup is: 1) Install with 'npm install -D eslint eslint-plugin-vue' and follow eslint-plugin-vue's configuration guide, 2) Setup ESLint IDE extensions to get linter feedback during development and avoid unnecessary linting cost when starting the dev server, 3) Run ESLint as part of the production build command to get full feedback before shipping, 4) Optionally setup tools like lint-staged to automatically lint modified files on git commit.
Custom blocks compilation with Vite
Custom blocks are compiled into imports to the same Vue file with different request queries. If using Vite, a custom Vite plugin should be used to transform matched custom blocks into executable JavaScript. Example: https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#example-for-transforming-custom-blocks
Custom blocks compilation with webpack
If using Vue CLI or plain webpack, a webpack loader should be configured to transform matched custom blocks. Example: https://vue-loader.vuejs.org/guide/custom-blocks.html
@vue/compiler-sfc package
@vue/compiler-sfc is part of the Vue core monorepo and is always published with the same version as the main vue package. It is included as a dependency and proxied under vue/compiler-sfc. It provides lower-level utilities for processing Vue SFCs and is only meant for tooling authors. Always use it via the vue/compiler-sfc deep import to ensure version sync with the Vue runtime.
@vitejs/plugin-vue official Vite plugin
@vitejs/plugin-vue is the official plugin that provides Vue SFC support in Vite. Documentation: https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue
vue-loader for webpack Vue SFC support
vue-loader is the official loader that provides Vue SFC support in webpack. Documentation: https://vue-loader.vuejs.org/. If using Vue CLI, see docs on modifying vue-loader options in Vue CLI.
Vue - Official provides Vue SFC formatting
The Vue - Official VS Code extension provides formatting for Vue SFCs out of the box.