Hana — VyuApp Support
Online
20/20 pesan tersisa
🌸 Selamat datang di VyuApp! Saya Hana, ada yang bisa saya bantu hari ini?
Semua artikel

Engineering

Vue.js 4 Composition API Patterns

Pelajari cara menggunakan Composition API di Vue 4 dengan TypeScript, reactive state management, dan performance optimization

14 Juli 2026 13 min read#vue#javascript#composition-api
Vue.js 4 Composition API Patterns

Vue.js 4 membawa perubahan besar pada cara pengembang menulis kode komponen. Composition API, yang pertama kali diperkenalkan di Vue 3, kini menjadi standar utama dengan peningkatan performa dan fitur yang lebih canggih. Berbeda dengan Options API yang mengorganisasi kode berdasarkan tipe (data, methods, computed), pendekatan ini memungkinkan kita mengelola kode berdasarkan fitur atau koncern yang spesifik.

Programmer sedang menulis kode Vue.js di layar monitor besar

Vue.js Composition API memungkinkan pengorganisasian kode berdasarkan fitur

Pada tahun 2026, ekosistem Vue telah sepenuhnya konsolidasi di sekitar Composition API dan pola TypeScript-compatible. Vue 3.6 membawa peningkatan performa yang signifikan, sementara Nuxt 4 dan Pinia 3 menjadi standar untuk aplikasi production-ready. Artikel ini membahas berbagai pola Composition API yang terbukti efektif untuk membangun aplikasi web yang scalable, maintainable, dan performant.

💡 Tips Penting

Jika Anda baru beralih dari Options API, mulailah dengan memahami ref() dan reactive() sebagai fondasi reactivity, lalu pelajari bagaimana lifecycle hooks seperti onMounted() dan watch() bekerja dalam konteks Composition API.

Mengapa Composition API Penting di Vue 4?

Composition API menawarkan cara yang lebih fleksibel untuk mengorganisasi kode dibandingkan Options API. Alih-alih memisahkan kode berdasarkan tipe (data, methods, computed, watch), kita bisa mengelompokkan logika yang terkait dalam satu fungsi yang terpisah. Ini membuat kode lebih mudah dipahami, diuji, dan dipelihara.

Salah satu tantangan terbesar Options API adalah ketika komponen tumbuh besar. Logika yang terkait harus dipisahkan ke beberapa bagian komponen, membuatnya sulit diikuti. Misalnya, logika terkait formulir harus dipisah antara data(), methods(), dan computed(), padahal ketiganya saling berkaitan erat. Composition API menyelesaikan masalah ini dengan memungkinkan kita menulis composable functions yang mengkapsulasi logika berdasarkan fitur.

Di Vue 4, peningkatan reactivity system mengurangi memory usage hingga 35% dan CPU cycles hingga 28%. Peningkatan ini menjadikan Composition API semakin relevan untuk aplikasi skala besar yang membutuhkan performa optimal. Dengan TypeScript yang terintegrasi secara native, developer juga mendapatkan pengalaman pengembang yang lebih baik dan pendeteksian error sejak di editor.

Ekosistem Vue 4 juga menghadirkan compiler yang lebih cerdas. Template compilation kini menghasilkan kode yang lebih optimal secara otomatis, sehingga developer tidak perlu khawatir tentang micro-optimizations manual. Fokus bisa tetap pada penulisan kode yang bersih dan terorganisir tanpa mengorbankan performa.

Arsitektur kode komponen Vue.js dengan struktur composition

Struktur arsitektur composable memungkinkan penggunaan kembali logic yang stateful

Composable: Konsep Dasar

Composable adalah fungsi yang memanfaatkan Composition API untuk mengkapitalisasi dan mereuse stateful logic. Berbeda dengan functions biasa yang hanya memproses input dan mengembalikan output (stateless logic), composable mengelola state yang berubah seiring waktu. Pola ini menjadi fondasi utama dalam pengembangan aplikasi Vue modern.

Contoh sederhana adalah tracking posisi mouse. Dalam skenario nyata, ini bisa berupa logika yang lebih kompleks seperti touch gestures atau koneksi ke database. Kunci utamanya adalah composable mengelola state yang persisten dan reaktif. Ketika state berubah, semua komponen yang menggunakan composable tersebut akan otomatis ter-update tanpa perlu trigger manual.

// Contoh composable sederhana: useMousePosition
import { ref, onMounted, onUnmounted } from 'vue'

export function useMousePosition() {
  const x = ref(0)
  const y = ref(0)
  
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }
  
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))
  
  return { x, y }
}

Composable mengembalikan refs yang bisa di-destructure oleh komponen yang menggunakannya. Ini menjaga reactivity tetap aktif meskipun nilainya di-destructure. Berbeda dengan reactive objects yang harus diakses sebagai satu kesatuan, refs bisa di-pass dan digunakan secara terpisah tanpa kehilangan reactivity.

Prinsip utama dalam membuat composable adalah setiap fungsi harus berdiri sendiri dan tidak bergantung pada konteks komponen tertentu. Ini memungkinkan composable untuk diuji secara terisolasi dan digunakan kembali di berbagai bagian aplikasi tanpa modifikasi. Pendekatan ini mempercepat pengembangan dan mengurangi bug akibat kode duplikat.

Tujuh Pola Desain Composables

Berdasarkan riset dari Michael Thiessen dan berbagai sumber komunitas, berikut adalah tujuh pola desain composables yang terbukti efektif di Vue.js 4. Setiap pola memiliki use case spesifik dan bisa dikombinasikan sesuai kebutuhan aplikasi. Pemilihan pola yang tepat akan mempengaruhi kualitas arsitektur kode secara keseluruhan.

1. Data Store Pattern

Pattern ini digunakan untuk membuat state global yang terpusat. Mirip dengan Pinia atau Vuex, tetapi lebih ringkas dan fleksibel. Cocok untuk mengelola state yang dibagikan di banyak komponen. Pattern ini menggunakan reactive objects yang di-expose melalui fungsi composable, sehingga state bisa diakses dan dimodifikasi dari mana saja dalam aplikasi tanpa prop drilling.

// useStore.js
import { reactive, readonly } from 'vue'

const state = reactive({
  darkMode: false,
  sidebarCollapsed: false,
  theme: 'nord'
})

export function useStore() {
  return {
    state: readonly(state),
    toggleDarkMode: () => state.darkMode = !state.darkMode,
    toggleSidebar: () => state.sidebarCollapsed = !state.sidebarCollapsed
  }
}

2. Thin Composables

Composable yang hanya melakukan satu hal dengan sangat baik. Prinsip Single Responsibility Principle (SRP) diterapkan di tingkat fungsi. Membuat kode lebih mudah diuji dan dipelihara karena setiap fungsi memiliki tanggung jawab yang jelas dan terbatas. Pattern ini mendorong pengembang untuk memecah logika kompleks menjadi unit-unit kecil yang fokus dan Independen.

3. Inline Composables

Composable yang didefinisikan langsung di dalam komponen, biasanya untuk logika yang hanya digunakan sekali. Tidak perlu diekstrak ke file terpisah jika hanya digunakan di satu tempat. Pattern ini cocok untuk logika sederhana yang tidak perlu direuse, seperti validasi form lokal atau transformasi data sekali pakai.

4. Dynamic Return

Pattern yang memungkinkan composable mengembalikan nilai berbeda berdasarkan parameter atau kondisi tertentu. Memberikan fleksibilitas dalam penggunaan dengan satu fungsi yang bisa menangani berbagai kasus. Misalnya, composable useFetch bisa mengembalikan data dalam format JSON atau text tergantung konfigurasi yang diberikan oleh developer.

5. Flexible Arguments

Composable yang menerima berbagai jenis argument: primitives, refs, atau reactive objects. Ini memudahkan penggunaan di berbagai konteks tanpa harus membuat beberapa versi fungsi yang sama. Composable yang dirancang dengan baik akan menangani semua tipe input secara konsisten dan memberikan output yang predictabel.

6. Async + Sync Pattern

Pattern untuk menangani operasi asynchronous (data fetching, API calls) yang mengembalikan both loading state dan data. Sangat umum digunakan untuk REST API integration dan data fetching di Vue 4. Pattern ini memisahkan concerns antara fetching logic, error handling, dan state management dengan cara yang bersih.

// useApi.js
export function useApi(url) {
  const data = ref(null)
  const loading = ref(false)
  const error = ref(null)
  
  async function fetchData() {
    loading.value = true
    error.value = null
    try {
      const response = await fetch(url)
      data.value = await response.json()
    } catch (e) {
      error.value = e.message
    } finally {
      loading.value = false
    }
  }
  
  onMounted(fetchData)
  return { data, loading, error, refetch: fetchData }
}

7. Options Object Pattern

Composable yang menerima object konfigurasi dengan default values. Memudahkan konfigurasi kompleks dengan tetap memberikan sensibilitas terhadap edge cases. Pattern ini sangat berguna untuk composable yang memiliki banyak parameter opsional, seperti useDebounce dengan konfigurasi delay, deep watch, atau capacity yang bisa disesuaikan.

// useDebounce.js
export function useDebounce(fn, options = {}) {
  const {
    delay = 300,
    deep = false,
    capacity = 10
  } = options
  
  // Implementation...
}

Nested Composables: Komposisi Logic Kompleks

Diagram alur data komponen Vue.js dalam arsitektur nested

Nested composables memungkinkan komposisi logic kompleks dari unit-unit kecil

Salah satu kekuatan terbesar Composition API adalah kemampuan untuk menanam (nest) composables. Satu composable function bisa memanggil satu atau lebih composable functions lainnya. Ini memungkinkan kita mengkomposisi logic kompleks menggunakan unit-unit kecil yang terisolasi dan Independen satu sama lain.

Mirip dengan cara kita mengkomposisi seluruh aplikasi menggunakan komponen, inilah mengapa kumpulan API yang memungkinkan pola ini disebut Composition API. Anda bisa membuat composable tingkat tinggi yang menggunakan beberapa composable tingkat rendah untuk menghasilkan fitur yang lebih kaya. Pola ini mencerminkan prinsip "composition over inheritance" yang menjadi fondasi arsitektur Vue.

// Nested composables example
import { useMouse } from './useMouse'
import { useWindowSize } from './useWindowSize'

export function useMouseInWindow() {
  const { x: mouseX, y: mouseY } = useMouse()
  const { width, height } = useWindowSize()
  
  const isInside = computed(() => {
    return mouseX.value <= width.value && 
           mouseY.value <= height.value
  })
  
  return { mouseX, mouseY, isInside }
}

Pola nesting ini memungkinkan pengembang membangun abstraksi tingkat tinggi tanpa mengorbankan modularitas. Setiap composable tetap berdiri sendiri dan bisa diuji secara terpisah, namun bisa dikombinasikan untuk menghasilkan fitur yang kompleks. Dengan approach ini, tim bisa membangun library composables yang reusable dan mudah dipelihara dalam jangka panjang.

Manfaat utama dari nested composables adalah kemampuan untuk membuat kode yang lebih deklaratif. Komponen tingkat atas cukup memanggil composable tingkat tinggi tanpa perlu mengetahui detail implementasi di bawahnya. Ini mengurangi coupling antar komponen dan mempermudah refactor di kemudian hari.

// Advertisement

Provide/Inject Patterns untuk State Sharing

Provide/Inject adalah pola penting untuk sharing state antar komponen tanpa prop drilling. Di Vue 4, pattern ini menjadi lebih fleksibel dengan dukungan TypeScript yang lebih baik dan integrasi dengan composables. Pattern ini memecahkan masalah umum di mana state harus diteruskan melalui banyak level komponen secara berurutan.

Pattern ini sangat berguna untuk kasus seperti theme management, authentication state, atau konfigurasi aplikasi yang perlu diakses di banyak level komponen. Dengan composables, kita bisa membungkus provide/inject menjadi fungsi yang lebih mudah digunakan dan lebih aman secara type-safe.

// theme-provider.js
import { provide, inject, ref } from 'vue'

const THEME_KEY = Symbol('theme')

export function useThemeProvider() {
  const theme = ref('light')
  
  function toggleTheme() {
    theme.value = theme.value === 'light' ? 'dark' : 'light'
  }
  
  provide(THEME_KEY, { theme, toggleTheme })
  
  return { theme, toggleTheme }
}

export function useTheme() {
  const themeContext = inject(THEME_KEY)
  if (!themeContext) {
    throw new Error('useTheme must be used within ThemeProvider')
  }
  return themeContext
}

Dengan membungkus provide/inject ke dalam composable, kita bisa membuat code yang lebih bersih dan reusable. Komponen cukup memanggil useTheme() untuk mengakses state tanpa perlu khawatir tentang mekanisme provide/inject secara langsung. Error handling juga lebih terpusat dan konsisten di seluruh aplikasi. Pattern ini juga memudahkan refactoring karena lokasi provide dan inject terpusat dalam satu file composable.

Provide/Inject patterns juga sangat efektif untuk testing. Kita bisa membuat mock provider yang menyediakan state palsu untuk testing, sehingga komponen bisa diuji secara terisolasi tanpa dependencies external. Pendekatan ini mempercepat proses testing dan mengurangi waktu debug secara signifikan.

Keuntungan lain dari pendekatan ini adalah kemampuan untuk membuat komponen yang benar-benar Independen dari struktur hierarki komponen. Tanpa provide/inject, komponen anak harus menerima props dari setiap parent secara berurutan. Dengan provide/inject, komponen bisa langsung mengakses state yang dibutuhkan tanpa memperdulikan posisinya dalam tree komponen.

Reactive Refs vs Reactive Objects

Developer sedang debugging kode Vue.js di layar ganda

Memahami perbedaan refs dan reactive objects sangat penting untuk Composition API

Di Composition API, ada dua cara utama membuat state reaktif: ref() dan reactive(). Memahami kapan menggunakan masing-masing adalah keterampilan penting yang mempengaruhi kualitas kode dan performa aplikasi secara keseluruhan.

⚠️ Perbedaan Penting

ref() membungkus value primitives (string, number, boolean) dan mengaksesnya melalui .value. Sedangkan reactive() membuat object atau array menjadi reaktif secara langsung tanpa perlu .value, tetapi tidak bisa digunakan untuk primitives.

Pilihan antara ref() dan reactive() bergantung pada konteks penggunaan. ref() lebih serbaguna karena bisa menangani semua tipe data, sementara reactive() lebih nyaman untuk object dengan banyak properti. Di Vue 4, kedua pendekatan ini dioptimasi dengan reactivity system yang lebih efisien dan memory footprint yang lebih kecil.

Sebagai best practice, gunakan ref() sebagai default untuk semua state. Hanya beralih ke reactive() saat Anda benar-benar membutuhkan ergonomi object langsung untuk objek dengan banyak properti yang diakses secara bersamaan dalam satu blok kode.

Lifecycle Hooks di Composition API

Lifecycle hooks di Composition API berbeda dari Options API. Alih-alih mounted(), updated(), dll., kita menggunakan onMounted(), onUpdated(), onUnmounted(), dan lainnya. Penamaan ini menggunakan prefix "on" untuk menunjukkan kapan hook tersebut dipanggil dalam siklus hidup komponen.

Hooks ini bisa dipanggil di dalam composable, memungkinkan composable untuk melakukan setup dan cleanup yang diperlukan. Ini sangat berguna untuk composable yang berinteraksi dengan browser APIs atau external services, seperti WebSocket connections atau DOM manipulations. Tanpa cleanup yang tepat, resources akan tetap aktif dan menyebabkan memory leaks yang merugikan performa aplikasi.

Setiap composable bisa memiliki lifecycle hooks sendiri-sendiri. Saat komponen yang menggunakan composable tersebut di-mount, semua onMounted hooks dari composable yang dipanggil akan ikut dieksekusi. Hal yang sama berlaku untuk hooks lainnya. Urutan eksekusi mengikuti urutan pemanggilan composable dalam komponen.

Variasi hooks yang tersedia di Composition API mencakup onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, dan onActivated/onDeactivated untuk komponen yang menggunakan keep-alive. Setiap hook memiliki timing yang spesifik dan berguna untuk skenario tertentu.

Dalam composable yang berinteraksi dengan API eksternal, pola umum adalah melakukan fetch data di onMounted dan cleanup connection di onUnmounted. Ini memastikan data diambil setelah komponen ter-mount di DOM dan resources dibersihkan saat komponen dihancurkan.

Best Practices untuk Production

Berdasarkan riset dari berbagai sumber termasuk Vue.js official documentation dan artikel best practices 2026, berikut adalah rekomendasi untuk penggunaan Composition API di production yang telah terbukti efektif:

  • Nama Composable: Gunakan prefix use untuk semua composable (useAuth, useFetch, useDebounce) agar konsisten dan mudah dikenali oleh developer lain dalam tim
  • Return Value: Selalu return object yang bisa di-destructure, bukan array, untuk memudahkan penggunaan dan reading kode oleh siapapun
  • TypeScript: Manfaatkan type inference untuk pengalaman pengembang yang lebih baik dan pendeteksian error sejak di editor sebelum kode dijalankan
  • Error Handling: Selalu handle error di dalam composable, jangan biarkan error propagating tanpa handling yang memadai
  • Cleanup: Pastikan semua effects di-cleanup di onUnmounted() untuk menghindari memory leaks yang bisa menurunkan performa
  • Composition: Buat composable kecil yang bisa di-compose, jangan buat composable yang terlalu besar atau melakukan terlalu banyak hal sekaligus

💡 Production Tip

Di Vue 4, pertimbangkan untuk menggunakan Pinia 3 sebagai state management solution daripada composable complex untuk global state. Pinia menawarkan integrasi DevTools yang lebih baik dan lebih mudah di-debug dalam lingkungan pengembangan. Untuk state lokal yang sederhana, composable tetap menjadi pilihan yang tepat dan efisien.

Jika Anda ingin mempelajari lebih lanjut tentang framework Vue ecosystem, baca juga panduan lengkap Nuxt.js untuk memahami bagaimana Composition API terintegrasi dalam full-stack framework. Untuk perbandingan dengan framework lain, lihat tutorial Next.js 16 yang membahas pendekatan berbeda dalam pengembangan web modern.

Kesimpulan

Composition API di Vue 4 menawarkan fleksibilitas dan kekuatan yang luar biasa untuk membangun aplikasi web modern. Dengan memahami berbagai pola composable, Anda bisa menulis kode yang lebih maintainable, testable, dan scalable untuk skala produksi. Pola-pola yang dibahas dalam artikel ini telah terbukti efektif di ribuan aplikasi production Vue di seluruh dunia.

Mulailah dengan pola-pola dasar seperti Data Store Pattern dan Thin Composables, lalu tingkatkan ke pola yang lebih advanced seperti Nested Composables dan Async+Sync Pattern. Ingat untuk selalu mempertimbangkan konteks penggunaan dan kebutuhan spesifik aplikasi Anda. Jangan terburu-buru mengadopsi semua pola sekaligus, melainkan pelajari dan terapkan secara bertahap sesuai kebutuhan proyek.

Dengan sepuluh key points yang telah dibahas, Anda sekarang memiliki pondasi yang kuat untuk menguasai Vue.js 4 Composition API patterns dan membangun aplikasi production-ready yang performant. Terus eksplorasi dan berkontribusi ke komunitas Vue untuk tetap mengikuti perkembangan terbaru dari framework ini.

// Advertisement

Pertanyaan Umum (FAQ)

Apa perbedaan utama Composition API dan Options API di Vue 4?

Options API mengorganisasi kode berdasarkan tipe (data, methods, computed, watch), sementara Composition API mengorganisasi berdasarkan fitur atau koncern. Composition API memungkinkan logika yang terkait dikelompokkan dalam satu fungsi composable, membuat kode lebih mudah dipahami dan diuji saat komponen tumbuh besar dan kompleks.

Kapan sebaiknya menggunakan ref() dibandingkan reactive()?

Gunakan ref() untuk primitives (string, number, boolean) dan saat Anda perlu pass state antar fungsi. Gunakan reactive() untuk object dengan banyak properti yang diakses secara bersamaan. Di Vue 4, ref() lebih fleksibel karena bisa menangani semua tipe data dengan cara yang konsisten.

Bagaimana cara menghindari memory leaks di composable?

Selalu lakukan cleanup di onUnmounted() untuk semua effects yang dibuat, seperti event listeners, timers, atau WebSocket connections. Tanpa cleanup, resources akan tetap aktif meskipun komponen sudah tidak ditampilkan, menyebabkan memory leaks yang bisa menurunkan performa aplikasi secara signifikan.

Apakah Composition API wajib digunakan di Vue 4?

Tidak wajib, tetapi sangat direkomendasikan. Options API masih didukung di Vue 4, tetapi Composition API menawarkan fleksibilitas yang lebih baik untuk TypeScript, code reuse melalui composables, dan pengorganisasian kode yang lebih rapi untuk aplikasi skala besar.

Bagaimana cara menguji composable secara terpisah?

Composable bisa diuji dengan memanggilnya di test setup dan memverifikasi return values-nya. Gunakan @vue/test-utils untuk testing composable yang membutuhkan lifecycle hooks. Setiap composable harus berdiri sendiri dan tidak bergantung pada komponen tertentu agar bisa diuji secara terisolasi.

Sumber Referensi

// Advertisement

V

VyuApp Studio

Bespoke web engineering — Garut, ID