
Make your websites/apps fast with strategies like lazy loading, stable prop design, virtual lists, v-once and v-memo, plus more!
Daniel Kelly
September 16, 2024
Vue.js is known for its excellent performance out of the box, but as applications grow in complexity, it's crucial to implement optimization techniques to ensure they remain fast and responsive. This article will explore various strategies to enhance the performance of your Vue.js applications.
TLDR: Checkout out course all about optimizing your Vue.js apps for blazing fast performance TODO: insert link here
Lazy loading is a technique that delays the loading of non-critical resources at page load time. In Vue.js, this can be achieved using dynamic imports.
Example:
const UserDashboard = () => import('./components/UserDashboard.vue')
const router = createRouter({
routes: [
{ path: '/dashboard', component: UserDashboard }
]
})
If you’re working in a Nuxt application this is automatically done for routes, and components can be lazy loaded by prefixing them with the Lazy keyword.
<LazyMyComponent v-if="showMyComponent" />
Vue.js provides two directives for conditionally rendering elements: v-show and v-if. Understanding when to use each can improve your app's performance.
Example:
<!-- Frequently toggled -->
<div v-show="isVisible">Heavy content</div>
<!-- Rarely changed -->
<div v-if="isLoggedIn">
<user-profile></user-profile>
<user-settings></user-settings>
</div>
When using v-for to render lists, always use the key attribute with a unique value. This helps Vue optimize re-renders and improves overall performance.
Example:
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
When dealing with large datasets, rendering all items at once can significantly slow down your application.
Example using a third-party library like vue-virtual-scroller:
<template>
<RecycleScroller
class="scroller"
:items="items"
:item-size="32"
>
<template v-slot="{ item }">
<div class="user">
{{ item.name }}
</div>
</template>
</RecycleScroller>
</template>
Not all data has to be defined as reactive data with the ref function. If it’s some hardcoded configuration object you can save a bit of memory as Vue doesn’t have to watch the data for changes.
ref or reactive function.ref or reactivif you do need reactivity.Example:
<script setup>
const navItems = [
{ label: "Home", link: "/" },
{ label: "About", link: "/about" },
{ label: "Blog", link: "/blog" },
{ label: "Contact Me", link: "/contact" },
]
</script>
<template>
<nav>
<ul>
<li v-for="item in navItems" :key="item.link" >
...
</li>
</ul>
</nav>
</template>
By default, Vue is deeply reactive. This is great for DX but can cause performance issues with large datasets. Replace ref with shallowRef when working with arrays with 1000s of items and trigger updates by replacing the entire array.
shallowRef.Example:
const mySuperBigArray = shallowRef([
// thousands of items in here
]);
function addNewItemToMySuperBigArray(newItem){
// ❌ this won't trigger updates to the DOM
mySuperBigArray.value.push(newItem)
// ✅ instead replace the entire dataset
mySuperBigArray.value = [...mySuperBigArray.value, newItem]
}
Vue.js provides two powerful directives, v-once and v-memo, that can help optimize rendering performance by skipping unnecessary updates to parts of your template.
The v-once directive renders an element or component once and then skips future updates. This is useful for content that never needs to change.
v-once for static content that won't change after initial render.v-once on elements that might need to update based on changing data.Example:
<template>
<div>
<!-- This will only be rendered once -->
<h1 v-once>{{ title }}</h1>
<!-- This will update as usual -->
<p>{{ dynamicContent }}</p>
</div>
</template>
The v-memo directive allows you to memoize a sub-tree of your template. It takes an array of dependencies and only re-renders the sub-tree when one of these dependencies changes.
v-memo for expensive sub-trees that depend on specific values.v-memo, as it adds complexity and can harm performance if used incorrectly.Example:
<template>
<div>
<div v-memo="[item.id, item.completed]">
<!-- This block will only re-render when item.id or item.completed changes -->
<span>{{ item.name }}</span>
<span>{{ item.description }}</span>
<complex-component :data="item.data"></complex-component>
</div>
</div>
</template>
In this example, the content inside the v-memo directive will only re-render if item.id or item.completed changes, even if other properties of item are updated.
In Vue, a child component only updates when at least one of its received props has changed. Therefore you should design props to change only when necessary.
Example:
<!-- ❌ this will re-render every ListItem component
in the list when activeId changes-->
<ListItem
v-for="item in list"
:id="item.id"
:active-id="activeId" />
<!-- ✅ this will only re-render the ListItem that's becoming active
and the one that is becoming inactive-->
<ListItem
v-for="item in list"
:id="item.id"
:active="item.id === activeId" />
Optimizing Vue.js applications involves a combination of using Vue's built-in features effectively and implementing general web performance best practices. By applying these techniques, you can ensure your Vue.js applications remain fast and responsive, providing an excellent user experience even as they grow in complexity.
Remember, performance optimization is an ongoing process. Always measure the impact of your optimizations using Vue's devtools and browser performance profiling tools to ensure you're making meaningful improvements.
If you'd like to test your skills and deepen your knowledge of making your Vue.js apps performant, checkout the Senior Vue.js Developer Exam.
Get the latest news and updates on developer certifications. Content is updated regularly, so please make sure to bookmark this page or sign up to get the latest content directly in your inbox.

Document Fragments: The Secret to Fast, Clean DOM Manipulation in JavaScript
Discover how DocumentFragment can dramatically speed up DOM manipulation in JavaScript. Learn how to batch element creation in memory, avoid reflows, and build smoother, faster interfaces with clean, efficient code.
Martin Ferret
Nov 6, 2025

Wait for that tick
Learn how Vue's nextTick works, why DOM updates are batched, and how to avoid timing issues when working with refs and animations.
Abdel Awad
Nov 5, 2025

Exploring Server Components in Nuxt
Nuxt offers experimental features like Server Components to take make performant applications. Let’s take a look back at how hydration works and how Nuxt handles Server Side Rendering.
Reza Baar
Nov 5, 2025
We can help you recruit Certified Developers for your organization or project. The team has helped many customers employ suitable resources from a pool of 100s of qualified Developers.
Let us help you get the resources you need.
