- tRPC adalah alat yang berbagi inferensi TypeScript dalam aplikasi full-stack TypeScript, sehingga mengurangi ketidaksesuaian tipe API antara server dan klien
- Saat API server diubah, dampaknya bisa langsung terlihat di kode klien melalui error TypeScript dan autocomplete, sehingga beban refactoring berkurang
- Berjalan tanpa skema terpisah atau tahap code generation, sehingga API type-safe dapat disusun tanpa menambah proses build maupun beban runtime
- Menyediakan adapter yang dapat dipasang ke berbagai lingkungan JavaScript seperti React, Next.js, Express, Fastify, AWS Lambda, Solid, dan Svelte
- Alur dasarnya adalah mendefinisikan procedure, membuat server HTTP, lalu menghubungkan klien dengan meneruskan tipe
AppRouter; tujuannya memberikan pengalaman pengembangan seperti memakai kode server API sebagai SDK
Cara tRPC mengubah pengembangan API
- tRPC meningkatkan produktivitas di aplikasi full-stack dengan memungkinkan server dan klien memanfaatkan informasi tipe TypeScript yang sama
- Intinya adalah memudahkan pembuatan API end-to-end type-safe dan mengurangi pekerjaan berulang pada lapisan API tradisional
- Jika perubahan di sisi server memengaruhi penggunaan di klien, TypeScript akan memberi tahu lewat error, sehingga ketidaksesuaian tipe di batas klien-server bisa cepat diketahui
Fitur utama yang dirasakan developer
-
Keamanan tipe otomatis
- Saat perubahan di sisi server memengaruhi kode klien, hal itu muncul sebagai error TypeScript
-
Pengalaman developer yang cepat
- tRPC tidak memiliki tahap build atau kompilasi
- Dapat digunakan tanpa code generation, beban runtime, atau proses build terpisah
-
Independen dari framework
- Dapat digunakan di berbagai framework JavaScript dan runtime
- Mudah ditambahkan ke proyek yang sudah ada
-
Autocomplete
- Memberikan pengalaman memperlakukan kode server API seperti SDK
- Saat menggunakan endpoint, developer bisa mendapat petunjuk berbasis tipe
-
Footprint klien kecil
- tRPC tidak memiliki dependensi dan berukuran kecil di sisi klien
-
Adapter bawaan
- Menyediakan adapter untuk React, Next.js, Express, Fastify, AWS Lambda, Solid, Svelte, dan lainnya
Alur penggunaan dasar
- API tRPC dimulai dengan mendefinisikan procedure terlebih dahulu
- Procedure adalah fungsi yang menyusun backend; dapat dikomposisi dan dibuat sebagai query, mutation, maupun subscription
- Beberapa procedure digabungkan ke dalam router
-
Mendefinisikan procedure
- Dalam contoh, instance tRPC dibuat dengan
initTRPC.create(), lalurouterdanpublicProceduredisusun - Procedure
greetingmenerima stringnamesebagai input dan mengembalikan string dalam bentukHello ${input.name} - Untuk validasi input, digunakan Zod agar input klien persis sesuai dengan bentuk yang diharapkan procedure
- Di akhir file, tipe router diekspor dengan
export type AppRouter = typeof appRouter;agar dapat digunakan di kode frontend
- Dalam contoh, instance tRPC dibuat dengan
-
Membuat server HTTP
- tRPC server dijalankan dengan meneruskan
appRouterkecreateHTTPServer - Dalam contoh,
listen(3000)dipanggil agar API listening di port3000 - tRPC menyediakan adapter untuk Next.js, Express, lingkungan berbasis Fetch API, Fastify, AWS Lambda, dan server vanilla Node HTTP
- Contoh lingkungan berbasis Fetch API mencakup Astro, Remix, SvelteKit, dan Cloudflare Workers
- tRPC server dijalankan dengan meneruskan
-
Menghubungkan klien dan menjalankan query
- Setelah server berjalan, klien dapat dibuat dengan
createTRPCClient<AppRouter>dan digunakan untuk melakukan query data - Contoh klien memakai
httpBatchLinkuntuk terhubung kehttp://localhost:3000 - Procedure
greetingdi server dapat digunakan dengan pemanggilan sepertitrpc.greeting.query({ name: 'John' }) - Dengan meneruskan tipe
AppRoutersaat membuat klien, developer mendapatkan autocomplete TypeScript dan IntelliSense yang sesuai dengan API backend tanpa code generation
- Setelah server berjalan, klien dapat dibuat dengan
Template awal dan tujuan pembuatannya
- Tersedia Use this template sebagai template yang bisa dicoba langsung
- Pembuat tRPC membuat tRPC untuk mengurangi kebutuhan akan lapisan API tradisional, sekaligus memberi keyakinan bahwa aplikasi tidak rusak meski pengembangan dilakukan cepat dan iteratif
- tRPC digunakan oleh tim teknologi terdepan dan sejumlah perusahaan Fortune 500
Respons developer
- Dalam beberapa kutipan developer, tRPC dinilai sebagai alat yang meningkatkan kualitas kode, kecepatan delivery, kepuasan developer, refactoring di batas klien-server, validasi input, dan pengalaman middleware bertipe
- Dalam monorepo TypeScript, tRPC diterima sebagai opsi yang lebih sederhana namun tetap menyediakan tipe yang kuat dibanding plain REST atau GraphQL
- Diperkenalkan use case di mana meski payload Stripe API dikembalikan dari server, tipe data respons tetap bisa diterima di komponen React
1 komentar
Komentar Hacker News
Saat ini kami sedang menghapus tRPC dari codebase, dan itu terasa seperti mimpi buruk karena coupling yang kuat
Ada sisi yang membuat developer junior tidak terdorong memikirkan interface atau pola akses data, dan akhirnya muncul pemetaan yang mengalir begitu saja dari Prisma sampai ke komponen
Bagus untuk prototyping cepat, tetapi ketika nanti ingin memisahkan codebase, kita cepat terjebak di jalan buntu
Karena bisa diperluas ke bahasa di luar TypeScript, ini juga membantu saat memindahkan backend ke bahasa lain atau membuat klien mobile native seperti Swift dan Kotlin
tRPC itu bagus, tetapi pada akhirnya ia hanya lapisan transport antara backend dan frontend
Membiarkan struktur internal tRPC dipakai jauh ke dalam logika bisnis sama buruknya dengan tidak memiliki lapisan controller atau router yang mendefinisikan input, schema, dan pemisahan secara jelas
Jadi kalau nanti kami meninggalkan tRPC, sepertinya relatif sederhana; misalnya, memindahkan seluruh subsistem agar berjalan di atas queue juga tampaknya tidak sulit
Hal seperti ini punya learning curve, dan biasanya dimulai dari tipe yang tidak berguna dan tidak menjelaskan apa pun seperti
type FunctionIWroteTodayArgs = …Setelah beberapa iterasi, kita pelan-pelan menyadari bahwa tujuannya bukan menduplikasi kode, melainkan menjelaskan domain serta membuat tipe, interface, dan API yang dapat digunakan ulang dan bermanfaat
Jadi menurut saya, daripada mencabut tRPC, lebih tepat memperbaiki bagian itu bersama tim
Saya belum paham mengapa mendeklarasikan HTTP client di sisi server lalu mengonsumsinya di sisi client itu lebih buruk
Kami membuat layanan dan memakai pola yang digunakan semua konsumen seperti web interface atau CLI, dan fakta bahwa hal-hal ini tidak rusak merupakan peningkatan yang lebih besar daripada metode apa pun yang pernah saya lihat sebelumnya
Keluhan bahwa developer junior tidak memikirkan interface kemungkinan besar akan muncul sama saja dengan API apa pun, bukan hanya tRPC
Di Notion, kami sudah memakai gaya API yang mirip tRPC, dan API itu sudah ada sekitar 4 tahun sebelum tRPC
Dengan mapped types TypeScript, hal seperti ini mudah dibuat sendiri. Cukup buat tipe objek yang key-nya adalah nama API dan value-nya adalah tipe
{ request, response }Di sisi server, tiap handler API didefinisikan sebagai fungsi yang menerima
APIs["addUser"]["request"]dan mengembalikanPromise, sementara client mengeksposnya sebagai fungsi async dengan argumen dan tipe return yang samaStrategi ini kami gunakan untuk API internal berbasis HTTPS, API real-time berbasis WebSocket, IPC antara Electron dan Webview, serta IPC webview OS antara native iOS/Android dan Webview
Pada API native, sisi server menggunakan Swift atau Kotlin, jadi tipe request/response kami tulis ulang secara manual di TypeScript. Suatu hari mungkin kami akan beralih ke format biner dengan IDL sendiri, tetapi untuk satu API lintas bahasa yang tumbuh perlahan, biaya developer experience dari sesuatu seperti Protobuf belum terasa sepadan
Tidak sempurna, tetapi menyediakan interface API yang cukup baik dengan tipe request/response
Kami juga membuat wrapper API tiruan 10 baris yang bisa dipanggil seperti
mockApi((request) => response), memeriksa tipe apakah fungsi tiruan tersebut mengimplementasikan API dengan benar, dan mengembalikan fungsi yang bentuknya persis sama dengan fungsi API sungguhan[0]: https://github.com/ferdikoomen/openapi-typescript-codegen
Sepertinya ini tidak sering dibahas karena belum ada library yang dikelola dengan baik dan dipromosikan luas yang mengadopsi pendekatan semacam ini
Saat memakai tRPC, JSON Schema dengan type generation, atau Zod, nilai pentingnya memang ada di bagian itu
Bahkan diminta menyediakan argumen generic secara langsung saat memanggil, yang cukup tidak menyenangkan saat mencoba menjaga dependency tree tetap rapi
https://github.com/mikew/transmission-material-ui/blob/maste...
https://github.com/mikew/transmission-material-ui/blob/maste...
Saya sangat menyukai tRPC. Mengagumkan bagaimana di stack khusus TypeScript, ia mendorong pengalaman developer sampai batasnya, dan membuat komunitas GraphQL menyadari batasan serta kompromi bahasa kueri
Pada saat yang sama, tRPC benar-benar melewati siklus tren dengan sangat cepat, dan tampaknya tidak ada perpindahan besar-besaran dari REST dan GraphQL ke RPC
Namun belakangan ini minat terhadap RPC tampaknya besar, dan di framework BFF yang kami buat (https://wundergraph.com/), kami juga mengadopsi sebagian ide dari tRPC dan NextJS lama, menggabungkan routing berbasis file dengan RPC
Selain tRPC, kami otomatis membuat JSON Schema untuk setiap operasi, dan juga menghasilkan spesifikasi OpenAPI untuk seluruh kumpulan operasi
Orang-orang menyukai pendekatan ini karena kumpulan endpoint RPC bisa dibagikan dengan mudah sebagai spesifikasi OpenAPI atau koleksi Postman. Hampir tidak ada perdebatan soal HTTP verb, dan pada praktiknya hanya ada kueri, mutasi, dan langganan
Saya penasaran bagaimana orang-orang sekarang memakai API bergaya GraphQL, REST, dan RPC, serta berapa banyak orang atau tim yang terlibat dalam API
Untuk REST API ada ts-rest(https://ts-rest.com), zodios(https://www.zodios.org), Hono(https://hono.dev)
Jika tim memakai beberapa bahasa, ada juga Fern: https://www.buildwithfern.com
Kami membuat tipe GraphQL setiap kali skema federasi berubah, dan membuat tipe respons untuk kueri serta mutasi setiap kali file disimpan
Itu juga bisa diabstraksikan dengan mudah memakai library pembuat consumer endpoint, tetapi selain itu saya tidak tahu apa yang benar-benar didapat dibandingkan web API biasa
Toh pekerjaan yang harus dilakukan pada tiap panggilan backend tetap harus dilakukan
Saya suka tRPC. Sejauh ini, ini jelas pengalaman developer full-stack terbaik yang pernah saya lihat, dan API-nya benar-benar luar biasa, khususnya jika dipakai bersama Zod
Saya melihat Zod dan tRPC sebagai proyek penting bagi masa depan TypeScript, dan rasanya dalam beberapa tahun ke depan pengalaman developer yang terinspirasi tRPC akan berkembang luas di seluruh ekosistem TypeScript
Proyek yang DNA tRPC-nya sudah jelas antara lain UploadThing dari Ping(https://github.com/pingdotgg/uploadthing) yang menyasar use case berbeda, dan Lusat kami(https://github.com/lusatai/lusat)
Selain itu, tipe error validasinya berubah tergantung skema apa yang diperiksa, dan itu juga merepotkan. Penanganan error jadi sulit diprediksi dan selalu terlalu banyak kasus pengecualian
Masih banyak ruang untuk perbaikan
Menulis unit test juga jadi jauh lebih mudah
Masalah besarnya tampaknya CRUD yang type-safe dan migrasi data; Mongoose memang sering disebut, tetapi dari sisi type safety rasanya jauh mundur dibanding Zod/TypeScript
Sekarang saya agak ingin melebih-lebihkan, tetapi untuk gaya pemrograman tertentu, bisa dibilang menambahkan Zod ke codebase memberi manfaat sebesar menambahkan TypeScript
Pola membuat service bertipe yang dimulai dari skema cocok untuk orang-orang yang condong ke functional programming
Saya penasaran bagaimana tRPC menangani perbedaan versi dan migrasi
Field punya siklus hidup. Saat pertama diperkenalkan, klien maupun server mana pun belum mengetahui field itu
Klien dan server tidak semuanya direstart sekaligus, dan juga tidak memiliki tipe versi yang sama
Data akan ditulis dengan tipe versi tertentu dan dibaca dengan tipe versi lain
Jika bisa menjamin semua binary, program yang sedang berjalan, dan data di-upgrade, serta tidak ada data persisten, mungkin itu bukan masalah
Namun begitu beberapa organisasi terlibat, sulit menjamin semua aplikasi dan server tersinkron dengan versi library terbaru, dibangun ulang, dan dideploy ulang
Pemeriksaan tipe statis mengasumsikan tidak ada perbedaan versi. Semua kode di dalam binary adalah dunia tertutup yang dibangun dengan versi library yang sama yang mendefinisikan tipe
Zod bisa mengizinkan field yang tidak dikenal, lalu Anda bisa memindahkannya menjadi field opsional, dan setelah situasinya stabil, menjadikannya field wajib
Tentu saja, kelompok yang paling menginginkan hal-hal yang diberikan tRPC justru paling kecil kemungkinannya memikirkan masalah seperti ini
Jika hanya menargetkan satu bahasa, wajar saja tidak perlu skema atau code generation
Saya memakai tRPC di dua aplikasi web sekitar 50 ribu baris dan sangat menyukainya. Pengalaman developer-nya bagus
Namun masa tren tRPC sudah lewat cukup lama, dan rasanya tren RSC dengan cepat menyusul
Sekarang, meskipun sudah ada solusi yang stabil dan bagus seperti tRPC, semua orang hanya membicarakan apakah akan memakai RSC atau tidak
Saya tidak menentang RSC, tetapi diskusinya terlalu banyak. Saat membuat aplikasi masa kini, tRPC adalah pendekatan yang sangat praktis
Tambahan: RSC adalah React Server Components, dan membawa filosofi baca/tulis datanya sendiri
Singkatan yang mungkin tidak diketahui orang sebaiknya didefinisikan atau diberi tautan
Saya pernah memakai tRPC dan Next.js di beberapa proyek pribadi, dan pengalamannya bagus
Terutama jika digunakan bersama template yang sudah dikonfigurasi seperti Create T3 App(https://create.t3.gg/), kecepatan iterasinya sulit ditandingi
Saya tidak tahu soal tRPC sampai seorang developer yang pernah bekerja dengan saya memujinya habis-habisan, tetapi setelah mengetahuinya, tampak sangat jelas bahwa ini sesuatu yang bagus
Kami membuat aplikasi T3 bersama (tRPC, Next.js, Tailwind, TypeScript, Prisma), dan jika ingin melihatnya, ada di sini: https://github.com/stytchauth/stytch-t3-example
Saat bekerja dengan TypeScript, API yang type-safe benar-benar sangat membantu