# Performance Techniques — Vue.js

Source: https://www.skillbyai.com/en/vue/x-perf

> Render less, load less.

## Tools for faster apps

Measure first with Vue Devtools and browser performance tools, then apply targeted fixes. **Lazy loading**: lazy routes and `defineAsyncComponent(() => import(...))` split rarely used components into separate chunks. **KeepAlive**: wrapping dynamic components or a `RouterView` slot in `<KeepAlive>` caches instances instead of destroying them, preserving state; `include`/`max` control what is cached, and `onActivated`/`onDeactivated` fire on toggle. **shallowRef** tracks only `.value` replacement, avoiding deep conversion of large immutable data. **v-memo** (Vue 3.2+) skips re-rendering a subtree unless the listed values change, and **v-once** renders static content once. For very long lists, use virtual scrolling.

## Async components, KeepAlive, shallowRef and v-memo

Several techniques in one view.

```vue
<script setup>
import { ref, shallowRef, defineAsyncComponent } from 'vue'

// loaded only when first rendered
const HeavyChart = defineAsyncComponent(() => import('./HeavyChart.vue'))
import DataTable from './DataTable.vue'

// large data replaced as a whole, not mutated deeply
const rows = shallowRef([])
async function load() {
  rows.value = await (await fetch('/api/rows')).json()  // replacing .value triggers updates
}

const selectedId = ref(null)
const tab = ref('table')
</script>

<template>
  <KeepAlive :max="5">
    <component :is="tab === 'chart' ? HeavyChart : DataTable" :rows="rows" />
  </KeepAlive>

  <div v-for="row in rows" :key="row.id"
       v-memo="[row.id === selectedId]"
       @click="selectedId = row.id">
    {{ row.name }}
  </div>
</template>
```

## Do not optimise blindly

`v-memo` and `shallowRef` add complexity and can cause stale UI if dependencies are missed. Use them where profiling shows a real bottleneck.

**Quiz:** What is the main effect of wrapping a component in <KeepAlive>?

- [x] Its instance is cached when hidden, so state is preserved when shown again
- [ ] It is rendered on the server
- [ ] Its props become read-only
- [ ] It is loaded in a separate chunk

*Answer:* Its instance is cached when hidden, so state is preserved when shown again. Cached instances fire onActivated and onDeactivated.
