Belajar Vue - Caching & Performance
Series/Belajar Vue/Episode 14
Episode 14 of 24

Belajar Vue - Caching & Performance

Episode ini membahas performa dan caching di Vue: client-side caching dengan Vue Query dan local storage, memoization dengan computed dan watchEffect, lazy loading komponen, serta teknik mengoptimalkan render dan reaktivitas.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Pendahuluan

Aplikasi yang lambat membuat pengguna pergi sebelum data dimuat. Caching dan performance bukan fitur tambahan, melainkan bagian dari pengalaman pengguna. Semakin sedikit request yang terbuang dan semakin sedikit render yang tidak perlu, semakin cepat aplikasi terasa.

Episode 14 membahas strategi caching dan optimasi di Vue: client-side caching dengan Vue Query dan local storage, memoization dengan computed dan watchEffect, lazy loading komponen untuk code splitting, serta teknik mengoptimalkan render dan reaktivitas.

Client-side Caching dengan Vue Query

Install dan Setup

TanStack Query menyediakan cache data server di client:

Install Vue Query
npm install @tanstack/vue-query
JSPasang plugin Vue Query
import { createApp } from "vue";
import { VueQueryPlugin } from "@tanstack/vue-query";
import App from "./App.vue";
 
createApp(App).use(VueQueryPlugin).mount("#app");

VueQueryPlugin didaftarkan sekali di root. Setelah itu, semua query memakai cache internal dengan key, staleTime, dan invalidasi otomatis.

useQuery dengan staleTime

Query yang sering dipanggil bisa memakai data cache lebih lama:

JSQuery dengan cache
<script setup>
import { useQuery } from "@tanstack/vue-query";
 
const { data, isPending, error } = useQuery({
  queryKey: ["produk"],
  queryFn: async () => {
    const res = await fetch("/api/produk");
    return res.json();
  },
  staleTime: 5 * 60 * 1000,
});
</script>
 
<template>
  <p v-if="isPending">Memuat...</p>
  <p v-if="error">Gagal memuat</p>
  <ul>
    <li v-for="item in data" :key="item.id">{{ item.nama }}</li>
  </ul>
</template>

staleTime: 5 * 60 * 1000 membuat data dianggap segar selama lima menit, sehingga navigasi bolak-balik tidak mengirim ulang request.

Caching dengan Local Storage

Composable useLocalCache

Untuk data yang jarang berubah, simpan hasil fetch ke local storage dengan masa kedaluwarsa:

JSComposable useLocalCache
import { ref } from "vue";
 
export function useLocalCache(key) {
  const data = ref(JSON.parse(localStorage.getItem(key)));
 
  function simpan(nilai) {
    localStorage.setItem(key, JSON.stringify(nilai));
    data.value = nilai;
  }
 
  function hapus() {
    localStorage.removeItem(key);
    data.value = null;
  }
 
  return { data, simpan, hapus };
}

useLocalCache("produk-terbaru") membaca cache di awal dan menulis lewat simpan. Biasanya cache dibaca sebelum request dikirim dan ditulis setelah fetch selesai.

Memoization dengan computed dan watchEffect

computed untuk Nilai Mahal

computed meng-cache hasil dan hanya menghitung ulang saat dependensi berubah:

JSComputed di-cache
import { computed } from "vue";
 
const daftar = ref([]);
const totalBerat = computed(() =>
  daftar.value.reduce((total, item) => total + item.berat, 0)
);

totalBerat hanya dihitung ulang ketika daftar berubah, bukan setiap render. Ini mencegah perhitungan yang mahal dijalankan berulang kali.

watchEffect dengan Cleanup

watchEffect cocok untuk efek samping seperti interval atau pengiriman analitik, dan cleanup-nya mencegah kebocoran:

JSwatchEffect dengan cleanup
import { watchEffect } from "vue";
 
watchEffect((onCleanup) => {
  const timer = setInterval(() => {
    console.log("detak");
  }, 1000);
 
  onCleanup(() => clearInterval(timer));
});

onCleanup(() => clearInterval(timer)) dipanggil sebelum efek berjalan lagi atau saat komponen dilepas, sehingga tidak ada interval yang menganggur.

Lazy Loading dan Code Splitting

Komponen Async

Komponen besar dimuat hanya saat dibutuhkan:

JSAsync component
<script setup>
import { defineAsyncComponent } from "vue";
 
const ChartHarian = defineAsyncComponent(
  () => import("../components/ChartHarian.vue")
);
</script>
 
<template>
  <ChartHarian />
</template>

defineAsyncComponent(() => import(...)) memisahkan kode komponen ke chunk terpisah yang diunduh saat komponen dirender. Gabungkan dengan dynamic route dari episode 9 untuk pembagian kode yang menyeluruh.

Mengoptimalkan Render dan Reaktivitas

  • Gunakan shallowRef untuk data besar yang diganti utuh, bukan dimutasi per field.
  • Batasi reaktivitas: jangan buat reactive untuk nilai yang hanya dibaca sekali.
  • Selalu beri key yang stabil pada v-for.
  • Gunakan v-memo untuk daftar yang hanya berubah sebagian.

Tip

Ukur dulu sebelum optimasi. Gunakan Vue Devtools dan Performance panel untuk menemukan bottleneck yang nyata, baru terapkan teknik di episode ini.

Penutup

Episode 14 memberi kalian perangkat performa: Vue Query untuk cache data server dengan staleTime, local storage untuk data yang jarang berubah, computed dan watchEffect untuk memoization, defineAsyncComponent untuk code splitting, serta aturan reaktivitas yang hemat.

Inti yang harus dibawa pulang:

  • Vue Query menyimpan cache data server di client.
  • staleTime menentukan berapa lama data dianggap segar.
  • Local storage cocok untuk data jarang berubah.
  • computed meng-cache nilai turunan yang mahal.
  • defineAsyncComponent membagi kode komponen.
  • Ukur performa sebelum mengoptimasi.

Di episode 15 selanjutnya kita membahas performance optimization — profiling dengan Vue Devtools dan browser tools, mengoptimalkan re-render komponen, virtual scrolling untuk daftar besar, serta prefetching aset dan resource hints.