Belajar Microfrontend - Global State & Auth (Shared Across Remotes)
Episode 7 of 28

Belajar Microfrontend - Global State & Auth (Shared Across Remotes)

Membedah berbagi state global dan auth antar remote: pola event bus dengan CustomEvent, central store di host yang dibagikan via props, sharing auth token yang aman, dan implementasi di storefront dengan package shared-state (zustand).

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

Pendahuluan

Setelah routing bekerja di episode 6, muncul kebutuhan yang tak kalah penting: remote-remote harus berbagi data — user sedang login atau tidak, role mereka apa, dan berapa item di cart. Tanpa berbagi state, tiap remote akan menyimpan duplikat data yang cepat tidak sinkron.

Mengapa penting? Karena ini titik di mana "distributed system" di frontend benar-benar terasa. Memilih pola berbagi state yang salah akan menimbulkan kebocoran memori, state yang tidak sinkron antar remote, atau token yang disimpan tidak aman. Episode ini membahas pola-pola berbagi state & auth yang sehat.

Masalah

Remote butuh tahu: user login, role, dan cart count — tanpa menduplikasi state. Kalau setiap remote menyimpan salinan cart sendiri, lalu user menambah item di satu remote, remote lain tidak tahu. Solusi harus memungkinkan satu sumber data yang dipakai banyak remote.

Pola State di 2026

Event Bus (Window CustomEvents)

Cara paling sederhana dan robust: memakai CustomEvent pada window sebagai bus event. Remote mempublikasikan perubahan, yang lain mendengarkan.

Mempublikasikan event cart:updated
window.dispatchEvent(
  new CustomEvent('cart:updated', { detail: { cartCount: 3 } })
)
Mendengarkan di remote lain
window.addEventListener('cart:updated', (e) => {
  const { cartCount } = (e as CustomEvent).detail
  setBadge(cartCount)
})

Pattern event bus adalah tulang punggung komunikasi lintas remote (detail lanjutan di episode 18). Keunggulannya: tidak butuh dependency bersama selain kontrak nama event.

Central Store / Context di Host Dibagikan via Props

Alternatifnya: host memiliki central store (misal zustand) dan membagikan "handle" ke remote lewat props saat merender. Karena remote menerima store via props (bukan via React context lintas bundle), kita menghindari memecahkan singleton React context.

State di URL/Query untuk ID

Untuk identifier semi-publik seperti cartId atau orderId, simpan di URL/query. Untuk token yang sensitif, jangan di URL — simpan aman di cookie (HttpOnly jika ada backend).

Auth Token Sharing

Host Menyimpan Session; Remote Terima via Props

Prinsip kunci keamanan: host menyimpan session, dan remote menerima apa yang dibutuhkan via props — bukan mengakses storage host atau membuat fetch token sendiri. Ini menjaga kontrak antarmuka yang jelas antara host dan remote.

Host meneruskan auth ke remote via props
<AccountApp
  user={session.user}
  role={session.role}
  onLogout={handleLogout}
/>

Remote Sandbox: Jangan Akses Host Internals

Remote harus berinteraksi lewat contract via interface — props dan event — bukan menyentuh detail internal host (seperti variabel global atau storage khusus host). Ini menjaga isolasi dan memudahkan penggantian remote.

Warning

Jangan meneruskan token raw ke semua remote. Berikan remote hanya data yang dibutuhkannya (misal user dan role), bukan credential mentah. Auth untuk request API sebaiknya ditangani host atau di level gateway, bukan di tangan remote yang belum tentu tepercaya.

Implementasi di storefront

Package shared-state

Kita letakkan utas state di packages/shared-state memakai zustand:

packages/shared-state/src/store.ts
import { create } from 'zustand'
 
interface CartState {
  cartCount: number
  addToCart: (qty: number) => void
}
 
export const useCartStore = create<CartState>((set) => ({
  cartCount: 0,
  addToCart: (qty) =>
    set((s) => ({ cartCount: s.cartCount + qty })),
}))

Host memiliki dan membagikan store ini; remote menerimanya lewat props (bukan import langsung) agar tidak pecah singleton.

Cart Count Badge di Shell

Ketika remote cart menambah item, ia mempublikasikan event, dan badge di shell rela-id:

Shell: badge cart rela-id
useEffect(() => {
  const handler = () => {
    const n = useCartStore.getState().cartCount
    setBadge(String(n))
  }
  window.addEventListener('cart:updated', handler)
  return () => window.removeEventListener('cart:updated', handler)
}, [])

Penutup

Pada episode 7 ini, kalian telah memahami global state & auth antar remote.

Inti yang harus dibawa pulang:

  • Remote butuh data bersama (user, role, cart count) tanpa menduplikasi state.
  • Pola: event bus (CustomEvent) untuk notifikasi, central store di host dibagikan via props, state di URL untuk ID non-sensitif.
  • Auth token: host pegang session, remote terima via props; jangan sebarkan token raw.
  • Remote harus berinteraksi via kontrak interface, bukan internal host.
  • Implementasi: shared-state (zustand) di host, badge cart rela-id via event cart:updated.

Di episode 8 selanjutnya, kita akan membahas design system & styling bersama — package design-system, isolasi CSS (prefix, CSS Modules, CSS-in-JS, Web Components), theming dengan CSS variables, versioning semver, dan Storybook. Pastikan state kalian sudah terbagi!

Belajar Microfrontend - Global State & Auth (Shared Across Remotes) | Belajar Microfrontend