Kenapa React Router v7?
Ada beberapa alasan kenapa gue nggak pake Tanstack Start:
- Nggak suka sama APIs-nya, sintaksisnya kayak bloated. Di satu sisi bagus, nggak ada magic yang disembunyiin, tapi di sisi lain terlalu ribet buat orang pragmatis kayak gue.
- Masih baru banget. Ini nggak begitu masalah, karena gue suka nyobain teknologi baru, tapi, gue juga butuh solusi yang bener-bener bisa diandelin buat proyek gue berikutnya.
- Sejujurnya dokumentasinya lebih bikin bingung dibanding Remix. Kalo dibilang deskriptif, iya, tapi nggak straight to the point.
Walaupun begitu, gue suka beberapa hal dari Tanstack Start, kayak server functions dan end-to-end type safety-nya.
Sementara Sveltekit, gue harus belajar Svelte dulu. Gue bakal gas ini kalo ini proyek kantor~
Kenapa Remix?
Selain karena gue udah pelajarin dasar-dasar Remix dari tahun lalu, gue juga betah pakenya. Ini yang bikin gue akhirnya mutusin buat pake Remix. Tapi, saat gue mau coba baca-baca lagi, ternyata Remix yang baru ini udah di-merge ke React Router v7.
Karena gue datang dari Next.js, maka ada beberapa hal yang gue cari dan jadi alesan gue buat pindah ke React Router v7 (yang selanjutnya bakal gue sebut sebagai React Router):
Dev Server yang Lebih Ringan dan Cepet
Gue masih inget banget waktu masih pake Next.js, memory gue abis 3-4GB cuma buat jalain dev server doang, anjing. Klaim doang 10x faster bla-bla-bla, gue nyimpen perubahan aja nggak langsung reflect, musti nunggu beberapa detik dulu. Segitu gue pake Macbook M1.
Sementara di Remix, kalo gue bikin perubahan itu langsung reflek in no time alias instan banget. Memory juga nggak abis banyak, sejauh ini nggak pernah sampe lebih dari 1GB, tapi gue nggak tau kalo proyeknya lebih kompleks, let's see.
Ini sih yang jadi alesan yang signifikan gue suka sama React Router.
Routing yang Sentris
Gue dulu suka banget sama file-system routing-nya Next.js, karena bikin routing jadi gampang. Tinggal bikin file doang udah jadi route tanpa setup ini-itu. Tapi, ketika gue udah mulai bikin-bikin produk enterprise-nya Kredibel yang menurut gue cukup kompleks ini bikin gue sadar kalo file-system routing di Next.js ini nggak banget. Alesannya:
- Semakin panjang path, semakin dalem juga struktur foldernya.
- Kalo gue ganti path, gue pindahin lagi struktur foldernya.
- Next.js makin banyak file convention, kayak route groups salah satunya. Ini yang kadang bikin gue bingung buat nyari lokasi file buat route yang gue cari.
- Penamaan file yang sama ini yang bikin susah dicari dan bikin pusing, gue jadi harus semakin spesifik. Ngetik "page.tsx" doang kan nggak cukup, harus lebih spesifik lagi.
Sementara di React Router, mereka punya sistem routing yang sentris lewat file routes.ts. Kalo lo pernah pake Laravel, ini kayak web.php atau api.php lah, cuman di satu file yang sama. Kalo gini lebih bikin gampang. Misal, lo lagi nerusin kerjaan orang atau kerjaan lo sendiri setelah beberapa bulan dan lo lupa lokasi suatu route, lo tinggal buka aja file routes.ts. Di situ lo bisa tau kalo suatu route itu dia di-reference ke component yang mana. Gini contohnya:
Kalo mau ganti path? Tinggal ganti, nggak ada struktur folder yang diubah. Nyari file? nggak ada lagi tuh "page.tsx" yang bikin pusing. Struktur folder? Nggak harus ngikutin struktur path-nya. Dan juga nggak banyak file convention di dalam folder app, lo bisa naruh component atau apapun di folder tersebut tanpa khawatir terekspos ke publik atau perlu nandain pake simbol-simbol kayak _
atau ( )
. Utter woke nonsense!
Selesai itu Next.js!
Data Loading
Kalo di Next.js disebutnya data fetching, di React Router pake istilah data loading. Pada dasarnya sama aja cuman beda istilah aja. Untuk data loading di React Router, kita bisa nge-export fungsi loader
di dalem file yang disebut route module. Route module ini simpelnya file yang lo referensiin di file routes.ts. Kalo ada kode route("/home", "./home.tsx")
, nah, file home.tsx
itu yang disebut route module.
Contoh loader
di React Router:
Ini mirip sama getServerSideProps
-nya Next.js versi pages router. Fungsi tersebut nantinya bakal dieksekusi di server ketika route tersebut di-render buat initial load. Fungsi ini juga bakal dihapus dari client bundle, jadi lo nggak perlu khawatir buat pake API yang cuman boleh jalan di server (contoh: database).
Alternatif dari loader
ini ada lagi, yaitu clientLoader
. Lo udah bisa nebak bedanya apa, kan? Iya, bedanya fungsi ini bakal dieksekusi di client/browser.
Actions
Action ini fitur React Router yang lo bisa pake buat handle form submission. Sama kayak loader
, action
juga ada dua variant: action
yang dieksekusi di server; clientAction
yang dieksekusi di client/browser. Enaknya action di React Router, kita nggak musti bikin file baru cuman buat naro function-nya, alih-alih kita bisa nge-export action
di dalem satu file route module yang sama.
Fungsi action
juga bakal dihapus dari client bundle, jadi lo aman buat pake API yang cuman boleh jalan di server.
End-to-end Type Safety
End-to-end type safety dalam konteks ini simpelnya adalah lo bisa nulis kode di server dan client dengan tipe data yang sama. Lo nggak perlu khawatir dan capek-capek bikin tipe data yang sama di server dan client, React Router bakal ngurusin itu buat lo. Hal ini juga bisa lo di temuin di loader dan action.
Kalo lo liat contoh di atas, loader
itu ngasih return value yang tipe datanya otomatis di-infer. Jadi, ketika lo pake loaderData
di component, lo udah bisa dapet tipe data yang sesuai dengan apa yang lo return di loader
.
Ini keren, karena lo nggak perlu validasi manual di client atau server yang mungkin biasanya lo lakuin ketika pake fetch
.
Fitur Lainnya
Selain fitur-fitur di atas, React Router juga punya beberapa fitur lain yang biasanya kita butuhin:
- Streaming
- Error boundary
- Meta tags
- Prefetching
- Form component
- Testing
- Dan masih banyak lagi
Gue nggak bakal bahas semuanya di sini secara detail, beberapa yang umum aja yang bakal gue bahas.