Belajar Pinia - Scaling Store Architecture
Episode 19 of 23

Belajar Pinia - Scaling Store Architecture

Aplikasi besar menuntut struktur store yang jelas. Episode ini membahas struktur folder stores/ per fitur, konvensi penamaan store, action, dan getter, cara memecah store besar, serta code-splitting dengan dynamic store registration agar bundle tetap ramping.

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

Pendahuluan

Pinia membuat store kecil menjadi mudah — dan di situlah letak tantangan skala: bagaimana mengorganisir puluhan store tanpa kekacauan. Struktur folder, konvensi penamaan, dan strategi code-splitting menentukan apakah codebase kalian tumbuh sehat atau berantakan.

Episode 19 membahas arsitektur store di skala besar: struktur folder per fitur, konvensi penamaan, memecah store yang membengkak, serta dynamic store registration untuk bundle size.

Struktur Folder stores/ per Fitur

Prinsip utama: satu folder stores/ dengan satu file per domain. Nama file mengikuti nama store:

Struktur folder stores/
src/stores/
  auth.ts
  cart.ts
  user.ts
  ui.ts
  index.ts

stores/auth.ts berisi store auth, stores/cart.ts berisi store cart, dan seterusnya. index.ts bisa mengekspor ulang seluruh store agar import tetap rapi:

JSRe-export di index.ts
export * from './auth'
export * from './cart'
export * from './user'
export * from './ui'

export * from './auth' membuat komponen cukup mengimpor dari satu titik. Struktur datar seperti ini lebih mudah dijelajahi daripada menumpuk folder bersarang.

Konvensi Penamaan

Konsistensi penamaan adalah dokumentasi yang paling murah:

  • Store: use<Nama>Store — misalnya useCartStore.
  • Id store: nama fitur — cart, auth, user.
  • Getter: nama benda/nilai — totalPrice, isLoggedIn.
  • Action: kata kerja — addItem, checkout, fetchProfile.
JSKonvensi penamaan yang konsisten
export const useCartStore = defineStore('cart', {
  state: () => ({ items: [] as CartItem[] }),
  getters: {
    totalPrice: (state) => ...,
  },
  actions: {
    addItem(item: CartItem) { ... },
  },
})

totalPrice (getter, kata benda) dan addItem (action, kata kerja) membuat intent jelas saat dibaca di template. Konvensi ini juga membuat DevTools dan log lebih mudah dipahami.

Konsistensi ini bekerja seperti bahasa bersama dalam tim: saat developer baru membaca useWishlistStore().addItem(product), mereka langsung tahu bahwa method tersebut memodifikasi daftar wishlist tanpa harus membuka definisinya. Sebaliknya, penamaan seperti useStore().setData() memaksa pembaca menyelidiki apa sebenarnya yang diubah — biaya kognitif yang terlihat kecil, tetapi menumpuk di codebase besar. Jika kalian ragu memberi nama, pilih yang menggambarkan hasil akhir dari operasi tersebut, bukan cara kerjanya.

Memecah Store yang Membengkak

Tanda store terlalu besar: lebih dari satu tanggung jawab, atau state yang tidak pernah dipakai bersamaan. Solusinya pisahkan per domain:

JSSebelum dan sesudah dipecah
// Sebelum: satu store untuk semua
useShopStore -> { user, cart, wishlist, orders, reviews }
 
// Sesudah: store kecil per domain
useUserStore()
useCartStore()
useWishlistStore()
useOrderStore()

Memecah store besar membuat setiap bagian lebih mudah diuji dan lebih jarang memicu re-render yang tidak perlu. Koordinasi antar store tetap bisa dilakukan dengan pola composing dari episode 12.

Tanda kedua yang perlu diperhatikan adalah getter yang bergantung pada banyak field dari domain berbeda. Jika sebuah getter membaca state.cart, state.user, dan state.ui sekaligus, besar kemungkinan store tersebut menampung tiga domain sekaligus — dan perubahan pada satu domain akan memicu perhitungan ulang getter yang sebenarnya tidak terkait. Memecahnya berarti getter masing-masing store hanya memantau dependency miliknya sendiri.

Code-Splitting dan Dynamic Store Registration

Pinia mengaktifkan store saat pertama kali dipanggil. Manfaatkan ini untuk lazy-loading modul:

JSDynamic store registration
async function loadAdminStore() {
  const mod = await import('@/stores/admin')
  return mod.useAdminStore()
}

await import('@/stores/admin') membuat store admin hanya diunduh saat dibutuhkan. Dengan route-level lazy loading dan store yang ikut di-split, bundle utama tetap ramping untuk pengguna yang tidak pernah menyentuh fitur tertentu.

Tip

Ukur dahulu dengan bundle analyzer sebelum memutuskan code-splitting. Jika store kecil dan jarang dipakai, efeknya kecil; fokus pada modul besar dan route jarang dikunjungi.

Penutup

Episode 19 membekali kalian pola arsitektur untuk skala besar. Kalian sekarang bisa menyusun struktur folder stores/ per fitur, menerapkan konvensi penamaan yang konsisten, memecah store yang membengkak, dan memakai dynamic import untuk code-splitting.

Inti yang harus dibawa pulang:

  • Satu file per store di src/stores/, di-re-export lewat index.
  • Konvensi: use<Nama>Store, getter kata benda, action kata kerja.
  • Pecah store yang punya lebih dari satu tanggung jawab.
  • Store diaktifkan saat pertama dipanggil — manfaatkan lazy load.
  • Dynamic import membuat store fitur besar ikut ter-split.
  • Ukur bundle sebelum mengoptimasi code-splitting.

Di episode 20 selanjutnya kita akan membahas fitur stabil terbaru Pinia v4 — perbaikan types, kompatibilitas Vue 3.5+, integrasi @pinia/nuxt 1.x, serta kondisi ekosistem 2026 termasuk @pinia/testing 2.x dan Pinia Colada yang kini stabil.

Belajar Pinia - Scaling Store Architecture | Belajar Pinia