Vue.js
Performance Optimization
Frontend Development
Web Components
JavaScript

Improving performance for many Vue components on the same page

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

When a Vue page contains hundreds of components, the bottleneck is rarely "Vue is slow" in the abstract. The real cost usually comes from rendering too many nodes, tracking too much reactive state, or forcing large parts of the tree to update when only a small area actually changed.

Measure Before You Change Structure

Start by identifying whether the page is slow on initial render, during interaction, or while scrolling. Vue Devtools and browser performance tools are more useful here than guesswork.

Look for:

  • large lists rendered all at once
  • repeated parent re-renders
  • expensive computed values
  • watchers firing too often
  • oversized props objects flowing through many children

Without that baseline, teams often optimize the wrong layer.

Render Fewer Components

If the page shows a long list, virtualization is usually the biggest win. Rendering only the visible rows often matters more than micro-optimizing the component code itself.

vue
1<script setup>
2import { computed, ref } from "vue"
3
4const allRows = ref(Array.from({ length: 10000 }, (_, i) => `Row ${i}`))
5const start = ref(0)
6const visibleCount = 30
7
8const visibleRows = computed(() =>
9  allRows.value.slice(start.value, start.value + visibleCount)
10)
11</script>
12
13<template>
14  <ul>
15    <li v-for="row in visibleRows" :key="row">
16      {{ row }}
17    </li>
18  </ul>
19</template>

A real app would usually use a virtualization library, but the principle is the same: do not keep thousands of off-screen components alive if the user can only see a few dozen.

Keep Reactive State Narrow

A common performance problem is passing large reactive objects deep into the tree when a child needs only one or two fields. The more reactive references a component touches, the more opportunities there are for updates to cascade.

Instead of this:

vue
<UserCard :user="user" />

consider passing only what the child renders most of the time:

vue
<UserCard :name="user.name" :status="user.status" />

That reduces coupling and makes it easier to reason about why a child re-rendered.

Stabilize Expensive Subtrees

If parts of the UI almost never change, tell Vue that explicitly. In Vue 3, v-memo and v-once can help in the right situations.

vue
1<template>
2  <SidebarStats v-once />
3
4  <MessageRow
5    v-for="message in messages"
6    :key="message.id"
7    v-memo="[message.id, message.isRead]"
8    :message="message"
9  />
10</template>

Use these directives carefully. They are most effective when you already understand which props actually drive updates. They are not substitutes for clean state design.

Split Heavy Work Away from the Render Path

If a computed property performs heavy grouping, sorting, or filtering on every reactive change, the page can feel sluggish even when the DOM size is reasonable.

Move expensive transformations:

  • to the server when possible
  • to a one-time preprocessing step
  • to a memoized store layer
  • to a worker if the computation is large enough

A fast component is often one that receives already-prepared data instead of rebuilding derived structures during every render cycle.

Async Components and Event Strategy

If some panels are below the fold or behind tabs, load them lazily instead of shipping and mounting everything on first paint.

javascript
1import { defineAsyncComponent } from "vue"
2
3export default {
4  components: {
5    ReportsPanel: defineAsyncComponent(() => import("./ReportsPanel.vue"))
6  }
7}

Also review event listeners. Hundreds of components with their own global listeners or deep watchers can create unnecessary overhead. Prefer parent-level coordination when possible.

Common Pitfalls

  • Rendering huge lists directly instead of virtualizing them.
  • Passing large reactive objects through many layers when children need only a few fields.
  • Performing expensive sorting or filtering inside render-driven computed properties.
  • Adding optimization directives such as v-once without understanding when the data actually changes.
  • Focusing on tiny component tweaks while ignoring the much larger cost of DOM size and update frequency.

Summary

  • Vue pages with many components are usually limited by render volume and reactive churn, not by component count alone.
  • Virtualize long lists before chasing smaller optimizations.
  • Keep props and reactive dependencies narrow so updates stay local.
  • Move heavy data transformation work out of the hot render path.
  • Use async components and selective memoization only after measuring where the real cost is.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.