Skip to content
Architecture Programming

Feature-Based Frontend Architecture

By Romi Fadli, S.Kom. 7 min read Software Design
On this page
A features folder holding three feature folders — orders, users, reports — with a blue line flowing one way into stores, services and an HTTP client, and a purple line to a design system pinned at version 1.0.0

Feature-Based Frontend Architecture adalah bentuk yang saya berikan pada antarmuka web berbasis Vue: tiap layar dan komponen milik satu fitur tinggal di folder fitur itu, yang dipakai bersama beberapa fitur ditaruh di beberapa folder global, dan tiap request ke backend lewat satu HTTP client. Ini kesepakatan saya sendiri, bukan rancangan dari buku, dan saya memakainya ulang di tiap project Vue yang saya mulai.

Ini salah satu arsitektur yang saya pakai, dan ia mengisi bagian front end web. Aturan bisnis sistem saya tinggal di backend service di belakang antarmuka, jadi front end tak butuh lapisan-lapisan yang saya pakai di sana; yang ia butuhkan adalah struktur yang membuat layar mudah dicari, ditambah, dan dibuang.

Sekilas

AsalKesepakatan saya sendiri; dekat dengan Feature-Sliced Design yang disederhanakan, ditambah service layer
Saya pakai untukAntarmuka web berbasis Vue: admin panel, dashboard, aplikasi web
Tak saya pakai untukAplikasi Flutter, dan apa pun di luar browser
BahasaTypeScript dengan Vue 3
Posisi Feature-Based Frontend Architecture di antara arsitektur yang saya pakai.

Gagasannya secara singkat

A. Fitur adalah satuannya

Tiap fitur antarmuka — pesanan, user, laporan — punya folder sendiri berisi halaman-halamannya dan komponen yang cuma ia pakai. Bila sesuatu milik satu fitur dan tak dipakai di tempat lain, ia tinggal di folder fitur itu, termasuk service atau type miliknya sendiri bila tak ada fitur lain yang membutuhkannya.

B. Yang dipakai bersama tetap global, per jenis

Yang dipakai beberapa fitur masuk ke sekumpulan kecil folder global, satu per jenis: service yang memanggil backend, store yang memegang state bersama, type, layout, komponen bersama, konfigurasi, terjemahan, dan utilitas. Sepotong kode baru pindah dari folder fitur ke folder global ketika fitur kedua membutuhkannya.

C. Data mengalir satu arah

Halaman membaca dan mengubah state bersama lewat store, store memanggil service, dan service memanggil backend lewat satu HTTP client. Halaman juga boleh memanggil service langsung ketika tak ada state yang perlu dibagi. Tak ada bagian service atau store yang meng-import halaman atau komponen.

D. Satu design system, dikunci per versi

Lapisan tampilannya berasal dari design system saya sendiri, package terpisah berisi komponen dan design token. Tiap project membawa salinan hasil build-nya di folder bernama versinya, menjangkaunya lewat satu import alias, dan tak pernah menyuntingnya dengan tangan; memperbarui design system berarti menyinkronkan versi baru ke folder itu.

Kenapa saya memilihnya

Saya menemukan halaman lewat nama fiturnya. Ketika sesuatu di layar perlu diubah, saya tahu fitur mana pemiliknya, dan semua yang dibutuhkan fitur itu ada di satu folder. Saya tak perlu mengingat folder berbasis jenis mana saja yang memegang halaman, komponen, dan helper-nya.

Fitur mudah dibuang atau dipindah. Karena fitur menyimpan halaman dan komponennya bersama-sama, membuangnya sebagian besar cukup dengan menghapus satu folder, dan memindahkannya ke project lain sebagian besar cukup dengan menyalin satu folder. Folder global hanya memegang yang benar-benar dipakai bersama, jadi fitur jarang meninggalkan jejak di tempat lain.

Antarmuka tampil sama di semua project. Tiap project memakai design system yang sama, jadi tombol, tabel, form, dan warna berperilaku sama di mana-mana. Menguncinya per versi berarti project hanya berganti tampilan ketika saya memutuskan memperbaruinya, bukan karena kebetulan.

Akses ke backend ada di satu tempat. Tiap request lewat satu HTTP client, yang melampirkan access token dan, ketika backend menjawab bahwa token-nya kedaluwarsa, memperbaruinya sekali lalu mengulang request yang sedang menunggu. Tak ada halaman yang harus menangani autentikasi atau pengulangan sendiri.

Kesepakatan saya

Project Vue saya yang mengikuti arsitektur ini punya pohon src/ seperti berikut:

bash
src/
├── app/                # App.vue, main.ts, router/
├── features/
│   └── orders/
│       ├── views/      # halaman fitur ini
│       └── components/ # komponen yang cuma dipakai fitur ini
├── services/           # satu service per resource backend + httpClient.ts
├── stores/             # state bersama, satu store per urusan
├── layouts/            # bingkai halaman: app, admin, auth, public
├── shared/             # komponen yang dipakai beberapa fitur
├── types/              # type bersama
├── config/             # konfigurasi aplikasi
├── i18n/               # terjemahan
├── utils/              # helper kecil
└── themes/
    └── design-system-v1.0.0/   # build design system yang di-vendor, tak pernah disunting
FolderIsinyaBoleh meng-import
features/<name>/halaman dan komponen satu fitur, plus service atau type miliknya sendiri bila cuma ia yang butuhstore, service, shared, type, design system
stores/state bersama dan action yang mengubahnyaservice, type
services/satu module per resource backend, semuanya dibangun di atas satu HTTP clientHTTP client, type
shared/, layouts/komponen dan bingkai halaman yang dipakai beberapa fiturdesign system, store
Isi tiap folder utama dan arah import yang boleh ditempuhnya.

Service membungkus satu resource backend dan tak lebih:

typescript
// services/orderService.ts
import { httpClient } from './httpClient'
import type { Order } from '@/types/order'

export const orderService = {
  list: () => httpClient.get<Order[]>('/orders').then((r) => r.data),
  create: (input: Partial<Order>) => httpClient.post<Order>('/order', input).then((r) => r.data),
}

Design system dijangkau lewat import alias, jadi halaman menulis import { DataTable } from '@theme' tanpa tahu folder versi mana yang berdiri di baliknya. Mengganti versi berarti mengganti folder dan alias-nya, bukan tiap import.

Cara saya memeriksa project

Inilah pertanyaan yang saya ajukan kepada project Vue, diambil dari kesepakatan di atas:

BidangPertanyaan yang saya ajukanSumber
FiturApakah tiap halaman tinggal di folder fitur pemiliknya?fitur adalah satuannya
BerbagiApakah semua isi folder global dipakai paling sedikit dua fitur?yang dipakai bersama tetap global
ArahApakah service dan store menghindari import halaman dan komponen?data mengalir satu arah
Akses backendApakah tiap request lewat satu HTTP client itu?akses di satu tempat
Design systemApakah design system dipakai lewat alias-nya, di versi yang dikunci, dan tak pernah disunting di tempat?satu design system
PembuanganBisakah fitur dibuang dengan menghapus folder dan route-nya?mudah dibuang
Pertanyaan yang saya pakai untuk memeriksa project Vue.

Di mana saya tidak memakainya

Aplikasi Flutter

Aplikasi Flutter saya membawa logika aplikasi sungguhan di perangkat, jadi saya memberinya Clean Architecture, dengan lapisan presentation/ untuk layar-layarnya. Antarmuka web berbasis Vue sebagian besar menampilkan dan menyunting apa yang diputuskan backend, karena itulah ia tak butuh lapisan-lapisan tadi, sedangkan aplikasi Flutter butuh.

Rujukan

Arsitektur ini kesepakatan saya sendiri dan tak punya buku di belakangnya. Kerabat terdekatnya yang sudah bernama adalah Feature-Sliced Design, metodologi untuk menyusun project front end menurut lapisan dan irisan fitur; milik saya bentuk yang lebih sederhana dari gagasan yang sama, digabung dengan service layer untuk akses backend. Saya menyebutnya sebagai kemiripan, bukan sumber.

Istilah

Fitur
Satu wilayah antarmuka yang dikenali user sebagai satu kesatuan, misalnya pesanan atau user, beserta halaman dan komponennya.
Store
Tempat yang memegang state bersama beberapa halaman, beserta action yang mengubahnya. Di project Vue saya memakai Pinia untuk ini.
Service
Module yang membungkus satu resource backend dan mengubah panggilan HTTP-nya menjadi fungsi biasa.
Design system
Package bersama berisi komponen dan design token — warna, huruf, jarak — yang menjaga beberapa antarmuka tampil dan berperilaku sama.
Vendoring
Menyalin versi hasil build sebuah dependency ke dalam project itu sendiri, bukan memasangnya dari package registry.
Import alias
Nama pendek, misalnya @theme, yang dipetakan build tool ke folder sungguhan, sehingga import tak berubah ketika folder-nya berubah.

Technologies covered

  • Vue

About the author

Photo of Romi Fadli

Romi Fadli, S.Kom.

Solution Architect · Backend Engineer · Embedded Systems

In my day job I work as a solution architect. I design the system, lead the team that builds it — quality assurance, backend developers, a UI developer, DevOps and DevSecOps — and write the most critical modules myself, such as a certificate authority, a long-term PDF signer, and the core API of a personnel system.

I work across the whole stack that a running system actually needs. On the hardware side that means PCB design, microcontrollers, and embedded firmware — including RISC-V boards running FreeRTOS and Embassy, speaking MQTT over mutually authenticated TLS on a microcontroller with 64 KB of SRAM.

Most of my day-to-day work is software: Rust backends and API modules built on Clean Architecture, an OAuth2/OpenID Connect authorization server written from scratch, PAdES document signing, and certificate authorities — root CAs, timestamping authorities, and OCSP responders. I also build the frontends that sit on top of them.

Running all of that means infrastructure: Docker Compose stacks, networking, Mikrotik and RADIUS, observability with OpenTelemetry, and a steady habit of writing command-line tools and utilities for Linux when the existing ones do not fit.

Share

Enjoyed this?

Get an email when a new article is published.

Referenced by

One definition in the middle feeds both a phone layout with stacked cards and a bottom bar, and a desktop layout with a top menu and a table

Aplikasi browser Vue dari sistem kepegawaian aparatur sipil negara: portal swalayan tempat pegawai mengurus record dan mengusulkan perubahan, serta administrasi bagan organisasi berversi, data referensi, dan akun — dibangun dari beberapa definisi bersama, bukan satu halaman per record.

9 min read Read more →
A memory chip holding a key, circled by refresh arrows, beside a browser window where a signature stamp is being dragged into place on a PDF page

Aplikasi browser Vue dari platform penandatanganan dokumen: sesi disimpan di memori dan diperbarui oleh satu refresh berantrean, login PKCE, stempel ditaruh presisi di halaman PDF, verifikasi identitas dengan tantangan wajah, persetujuan client, dan administrasi berbasis role.

10 min read Read more →
Four concentric circles with arrows coming in from a database, a browser window, and a message queue, all pointing toward the centre.

Clean Architecture

Programming

Clean Architecture adalah salah satu arsitektur yang saya pakai: kenapa saya memilihnya, kesepakatan folder dan penamaan yang diikuti tiap module saya di Rust, Python, Dart, Node.js, dan C, pertanyaan yang saya pakai untuk memeriksa module, dan tempat saya memakai arsitektur lain.

12 min read Read more →