2 पॉइंट द्वारा GN⁺ 2023-08-13 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • tRPC फुलस्टैक TypeScript ऐप्स में TypeScript inference साझा करता है, जिससे सर्वर और क्लाइंट के बीच API type mismatch कम होता है
  • सर्वर API बदलने पर उसका असर क्लाइंट कोड में तुरंत TypeScript errors और autocomplete के जरिए दिख जाता है, जिससे refactoring का बोझ घटता है
  • यह अलग schema या code generation चरण के बिना काम करता है, इसलिए build process या runtime overhead बढ़ाए बिना type-safe API बनाई जा सकती है
  • यह React, Next.js, Express, Fastify, AWS Lambda, Solid, Svelte जैसी कई JavaScript environments के लिए adapters देता है
  • इसका बुनियादी flow है procedures define करना, HTTP server बनाना, और AppRouter type देकर client connect करना; इसका लक्ष्य API server code को SDK की तरह इस्तेमाल करने वाला developer experience देना है

tRPC API development का तरीका कैसे बदलता है

  • tRPC फुलस्टैक applications में सर्वर और क्लाइंट को एक ही TypeScript type information इस्तेमाल करने देता है, जिससे productivity बढ़ती है
  • इसका मुख्य उद्देश्य end-to-end type-safe API को आसानी से बनाना और पारंपरिक API layers में होने वाले दोहराव वाले काम को कम करना है
  • अगर सर्वर-साइड बदलाव का असर क्लाइंट usage पर पड़ता है, तो TypeScript errors के जरिए बता देता है, जिससे क्लाइंट-सर्वर boundary पर type mismatch जल्दी पकड़ा जा सकता है

डेवलपर्स को महसूस होने वाली मुख्य खूबियां

  • automatic type safety

    • सर्वर-साइड बदलाव का असर क्लाइंट कोड पर पड़े तो वह TypeScript errors के रूप में दिखता है
  • तेज developer experience

    • tRPC में कोई build या compile चरण नहीं है
    • इसे code generation, runtime overhead, या अलग build process के बिना इस्तेमाल किया जा सकता है
  • framework independence

    • इसे JavaScript frameworks और runtimes की पूरी रेंज में इस्तेमाल किया जा सकता है
    • मौजूदा projects में भी इसे आसानी से जोड़ा जा सकता है
  • autocomplete

    • यह API server code को SDK की तरह संभालने का अनुभव देता है
    • endpoints इस्तेमाल करते समय type-based hints मिलते हैं
  • छोटा client footprint

    • tRPC में कोई dependencies नहीं हैं और इसका client-side size छोटा है
  • included adapters

    • यह React, Next.js, Express, Fastify, AWS Lambda, Solid, Svelte आदि के लिए adapters देता है

बुनियादी उपयोग प्रवाह

  • tRPC API की शुरुआत पहले procedure define करने से होती है
  • procedure backend बनाने वाले functions होते हैं, जिन्हें compose किया जा सकता है और query, mutation, subscription के रूप में बनाया जा सकता है
  • कई procedures को एक router में बांधा जाता है
  • procedure define करना

    • उदाहरण में initTRPC.create() से tRPC instance बनाया जाता है, और routerpublicProcedure तैयार किए जाते हैं
    • greeting procedure input के रूप में name string लेता है और Hello ${input.name} के रूप में string लौटाता है
    • input validation के लिए Zod का उपयोग किया जाता है, ताकि क्लाइंट input ठीक उसी रूप में हो जिसकी procedure को अपेक्षा है
    • फ़ाइल के अंत में export type AppRouter = typeof appRouter; से router type export किया जाता है, ताकि उसे frontend code में इस्तेमाल किया जा सके
  • HTTP server बनाना

    • createHTTPServer को appRouter देकर tRPC server चलाया जाता है
    • उदाहरण में API को port 3000 पर listen कराने के लिए listen(3000) कॉल किया जाता है
    • tRPC Next.js, Express, Fetch API आधारित environments, Fastify, AWS Lambda, और vanilla Node HTTP server के लिए adapters देता है
    • Fetch API आधारित environments के उदाहरणों में Astro, Remix, SvelteKit, Cloudflare Workers शामिल हैं
  • client connect करना और query चलाना

    • सर्वर चलने के बाद createTRPCClient<AppRouter> से client बनाया जाता है और data query किया जा सकता है
    • उदाहरण client httpBatchLink का उपयोग करके http://localhost:3000 से जुड़ता है
    • trpc.greeting.query({ name: 'John' }) जैसी call से सर्वर की greeting procedure इस्तेमाल की जा सकती है
    • client बनाते समय AppRouter type देने पर backend API से मेल खाने वाला TypeScript autocomplete और IntelliSense बिना code generation के मिल जाता है

शुरुआत के templates और बनाने का उद्देश्य

  • सीधे आज़माने के लिए Use this template उपलब्ध है
  • tRPC के निर्माता ने इसे पारंपरिक API layers की ज़रूरत कम करने और तेज़ iteration के साथ ऐप के न टूटने का भरोसा देने के लिए बनाया था
  • tRPC का उपयोग अग्रणी तकनीकी टीमें और कई Fortune 500 कंपनियां कर रही हैं

डेवलपर प्रतिक्रियाएं

  • कई डेवलपर उद्धरणों में tRPC को code quality, delivery speed, developer satisfaction, क्लाइंट-सर्वर boundary refactoring, input validation, और typed middleware experience बेहतर करने वाले टूल के रूप में आंका गया है
  • TypeScript monorepo में इसे plain REST या GraphQL की तुलना में अधिक सरल लेकिन मजबूत typing देने वाले विकल्प के रूप में देखा जाता है
  • एक उपयोग मामला भी बताया गया है जिसमें सर्वर से Stripe API payload लौटाने पर भी React components में response data types मिल जाते हैं

1 टिप्पणियां

 
GN⁺ 2023-08-13
Hacker News की राय
  • अभी हमारे codebase से tRPC हटाने का काम चल रहा है, और tight coupling की वजह से यह किसी बुरे सपने जैसा था
    एक पहलू यह भी था कि junior developers को interfaces या data access patterns के बारे में सोचने से बचने के लिए प्रेरित करता था, और Prisma से components तक सीधी mapping बन गई थी
    तेज़ prototyping के लिए यह शानदार है, लेकिन बाद में codebase को अलग-अलग हिस्सों में बाँटने की कोशिश करें तो आप जल्दी ही dead end में फँस जाते हैं

    • schema का एक अनदेखा फायदा यही है। GraphQL जैसे schema आपको data types और contracts के बारे में सोचने पर मजबूर करते हैं, और code के अलग-अलग हिस्सों पर काम करने वाले लोगों के लिए तालमेल से काम करना आसान बनाते हैं
      यह TypeScript के बाहर की languages तक भी scale होता है, इसलिए backend को किसी दूसरी language में ले जाने या Swift, Kotlin जैसे native mobile clients बनाने में भी मदद करता है
    • हमारी company ने tRPC अपनाया है, और थोड़ी-सी upfront design के साथ हम code में “tight coupling” बनने वाली चीज़ों को अच्छी तरह अलग करके इस्तेमाल कर रहे हैं
      tRPC बहुत अच्छा है, लेकिन आखिरकार यह backend और frontend के बीच सिर्फ transport layer ही है
      tRPC के internal structure को business logic के अंदर गहराई तक इस्तेमाल होने देना उतना ही खराब है जितना input, schema और separation को साफ़-साफ़ define करने वाली controller या router layer का न होना
      इसलिए बाद में tRPC छोड़ना भी अपेक्षाकृत आसान होगा, और उदाहरण के लिए किसी पूरे subsystem को queue पर चलाने के लिए move करना भी मुश्किल नहीं लगता
    • समस्या tRPC नहीं, बल्कि उन engineers में अधिक है जो types को सिर्फ types लगाने के लिए इस्तेमाल करते हैं। कोई भी tool इस्तेमाल करें, वही समस्या आएगी
      ऐसी चीज़ों की learning curve होती है, और आम तौर पर शुरुआत type FunctionIWroteTodayArgs = … जैसे बेकार और कुछ भी explain न करने वाले types से होती है
      कुछ iterations के बाद धीरे-धीरे समझ आता है कि लक्ष्य code को duplicate करना नहीं, बल्कि domain को explain करना और reusable व उपयोगी types, interfaces और APIs बनाना है
      इसलिए tRPC को हटाने के बजाय team के साथ मिलकर उस हिस्से को बेहतर करना सही लगता है
    • coupling वाला nightmare हिस्सा थोड़ा और समझाएँ तो अच्छा होगा
      server side पर HTTP client declare करना और client side पर उसे consume करना क्यों ज़्यादा खराब है, यह मुझे ठीक से समझ नहीं आ रहा
      हम services बनाते हैं और ऐसे patterns इस्तेमाल करते हैं जिन्हें web interface या CLI जैसे सभी consumers use करते हैं, और इन चीज़ों के न टूटने की बात मेरे द्वारा पहले देखी गई किसी भी approach से बड़ा improvement रही है
    • छोटी team में हमारा अनुभव बिल्कुल उल्टा है, और लगता है कि पहले वाली बड़ी team में भी यह अच्छी तरह काम करता
      junior developers interfaces के बारे में नहीं सोचते—यह शिकायत tRPC ही नहीं, किसी भी API के साथ समान रूप से आने की संभावना है
  • Notion में tRPC जैसी API style इस्तेमाल होती रही है, और वह API tRPC से लगभग 4 साल पहले से थी
    TypeScript के mapped types से ऐसी चीज़ आसानी से खुद बनाई जा सकती है। keys API names हों और values { request, response } type वाले object type हों, बस इतना करना है
    server side पर हर API handler को APIs["addUser"]["request"] लेने और Promise return करने वाले function के रूप में define करें, और client पर उसे उन्हीं arguments और return type वाले async function के रूप में expose करें
    इस strategy को HTTPS internal API, WebSocket-based real-time API, Electron और Webview के बीच IPC, और iOS/Android native व Webview के बीच OS webview IPC में इस्तेमाल किया जाता है
    native APIs में server side Swift या Kotlin में होता है, इसलिए request/response types को TypeScript में हाथ से फिर से लिखते हैं। किसी दिन इसे अपने IDL वाले binary format में बदलेंगे, लेकिन धीरे-धीरे बढ़ने वाली single cross-language API के लिए Protobuf जैसी चीज़ों की developer experience cost अभी सार्थक नहीं लगी

    • मौजूदा project TypeScript frontend और Python backend का combination है, और OpenAPI schema को source of truth मानकर client side पर openapi-typescript-codegen [0] इस्तेमाल करता है
      यह perfect नहीं है, लेकिन request/response types के साथ काफ़ी अच्छा API interface देता है
      साथ ही mockApi((request) => response) की तरह call किया जा सकने वाला 10-line mock API wrapper बनाया है, जो type-check करता है कि mock function API को सही तरह implement करता है या नहीं, और असली API function जैसा ही दिखने वाला function return करता है
      [0]: https://github.com/ferdikoomen/openapi-typescript-codegen
    • यही approach सही है। tRPC केवल types infer करने से आगे अनावश्यक complexity जोड़ता है
      लगता है कि इस approach को अपनाने वाली अच्छी तरह maintain और promote की गई library अभी नहीं आई है, इसलिए इसकी चर्चा अक्सर नहीं होती
    • इस process में request data validation कैसे करते हैं, क्या कोई तरीका है, यह जानना चाहूँगा
      tRPC, JSON Schema और type generation, Zod जैसी चीज़ें इस्तेमाल करते समय असली value इसी हिस्से में होती है
    • sample code देखकर लगता है कि यह XHR calls के ऊपर typed wrapper जैसा है या नहीं, यह जानना चाहूँगा
      call करते समय generic argument खुद देने को भी कहता है, जो dependency tree को साफ़-सुथरा रखने की कोशिश करते समय काफ़ी खराब लगता है
    • यह approach असल में काफ़ी अच्छी तरह काम करती है
      https://github.com/mikew/transmission-material-ui/blob/maste...
      https://github.com/mikew/transmission-material-ui/blob/maste...
  • tRPC मुझे बहुत पसंद है। TypeScript-only stack में developer experience को चरम तक ले जाना कमाल की बात है, और इसने GraphQL community को query language की सीमाओं और trade-offs को पहचानने पर मजबूर किया
    साथ ही, tRPC ने hype cycle बहुत तेजी से पार कर लिया, और ऐसा नहीं लगता कि REST और GraphQL से RPC की ओर बड़े पैमाने पर migration हो रहा है
    हालांकि आजकल RPC में दिलचस्पी काफी दिखती है, और हमारे बनाए BFF framework(https://wundergraph.com/) में भी tRPC और पुराने NextJS के कुछ ideas अपनाकर file-based routing और RPC को जोड़ा गया है
    tRPC के अलावा, हर operation के लिए JSON Schema अपने-आप generate करते हैं, और पूरे operations set के लिए OpenAPI spec भी generate करते हैं
    RPC endpoints के bundle को OpenAPI spec या Postman collection के रूप में आसानी से share किया जा सकता है, इसलिए लोगों को यह approach पसंद आती है। HTTP verbs पर चर्चा भी लगभग नहीं होती, और practical तौर पर सिर्फ queries, mutations और subscriptions ही होते हैं
    जानना चाहूंगा कि आजकल लोग GraphQL, REST, RPC style APIs का इस्तेमाल कैसे कर रहे हैं, और API में कितने लोग या कितनी teams शामिल होती हैं

    • Garph, GraphQL के लिए tRPC जैसा है: https://garph.dev
      REST API side पर ts-rest(https://ts-rest.com), zodios(https://www.zodios.org), Hono(https://hono.dev) हैं
      अगर team में कई languages इस्तेमाल होती हैं, तो Fern भी है: https://www.buildwithfern.com
    • “GraphQL community को query language की सीमाओं और trade-offs को पहचानने पर मजबूर किया” वाले हिस्से को और समझा दें तो अच्छा होगा
      हम federated schema बदलने पर हर बार GraphQL types generate करते हैं, और file save करते समय हर बार queries और mutations के response types generate करते हैं
    • जो बात हमेशा ध्यान खींचती है, वह यह है कि verbs और paths काफी मामूली details हैं
      endpoint consumer generation library से इन्हें आसानी से abstract भी किया जा सकता है, लेकिन इसके अलावा सामान्य web API की तुलना में वास्तव में क्या ज्यादा मिलता है, समझ नहीं आता
      आखिरकार हर backend call में जो काम करना है, वह वैसे ही करना पड़ता है
  • tRPC पसंद है। अब तक देखे गए full-stack developer experience में यह साफ तौर पर सबसे अच्छा है, और खासकर Zod के साथ इस्तेमाल करने पर API सचमुच शानदार बनती है
    Zod और tRPC को मैं TypeScript के भविष्य के अहम projects मानता हूं, और लगता है कि अगले कुछ वर्षों में TypeScript ecosystem में tRPC से प्रेरित developer experience बड़े पैमाने पर खिलेगा
    जिन projects में tRPC का DNA पहले से साफ दिखता है, उनमें अलग use case को target करने वाला Ping का UploadThing(https://github.com/pingdotgg/uploadthing) और हमारा Lusat(https://github.com/lusatai/lusat) शामिल हैं

    • Zod मुझे ज्यादा पसंद नहीं है। types और generic parameters tricky और verbose हैं, object generics में data types पास नहीं कर सकते और Zod के अपने schema type को property के रूप में पास करना पड़ता है, जिससे यह messy और non-intuitive लगता है
      ऊपर से validation errors का type इस पर निर्भर करता है कि कौन-सा schema जांचा जा रहा है, यह भी परेशान करने वाला है। error handling unpredictable हो जाती है और edge cases हमेशा बहुत ज्यादा होते हैं
      improvement की काफी गुंजाइश है
    • हाल ही में एक personal project में tRPC और Zod इस्तेमाल किया, और सहमत हूं कि अनुभव सचमुच शानदार था
      unit tests लिखना भी काफी आसान हो गया
    • सोच रहा हूं कि MongoDB side पर इस तरह के क्षेत्र के tools हैं या नहीं
      बड़ा problem type-safe CRUD और data migration लगता है; Mongoose का नाम बहुत लिया जाता है, लेकिन type safety के मामले में यह Zod/TypeScript से काफी पीछे हटने जैसा महसूस होता है
    • Zod सचमुच जबरदस्त है
      अभी थोड़ा बढ़ा-चढ़ाकर कहने का मन है, लेकिन कुछ programming styles में codebase में Zod जोड़ना उतना ही बड़ा फायदा दे सकता है जितना TypeScript जोड़ना
    • effect/core और effect/schema भी recommend करता हूं
      schema से शुरू करके typed services बनाने का pattern functional programming की तरफ झुकाव रखने वालों को अच्छा suit करता है
  • उत्सुक हूं कि tRPC version differences और migrations को कैसे handle करता है
    fields का lifecycle होता है। जब वे पहली बार introduce होते हैं, तो कोई client या server उस field को नहीं जानता
    clients और servers एक साथ restart नहीं होते, और उनके पास types का एक ही version भी नहीं होता
    data एक version के type से लिखा जाता है और दूसरे version के type से पढ़ा जाता है
    अगर guarantee कर सकते हैं कि सभी binaries, चल रहे programs और data upgrade हो जाएंगे और persistent data नहीं है, तो शायद problem न हो
    लेकिन जैसे ही कई organizations शामिल होती हैं, यह guarantee करना मुश्किल हो जाता है कि सभी apps और servers latest library version से sync होंगे, फिर build होंगे और redeploy होंगे
    static type checking मानती है कि version differences नहीं हैं। binary के अंदर का सारा code types define करने वाली library के एक ही version से build किया गया closed world होता है

    • लगभग “खुद करना पड़ेगा” जैसा है
      Zod unknown fields allow कर सकता है, फिर आप उसे optional field में बदल सकते हैं, और situation stable होने पर required field बना सकते हैं
      बेशक, जिन लोगों को tRPC से मिलने वाली सुविधा सबसे ज्यादा चाहिए, वही इस तरह की problems के बारे में सोचने की सबसे कम संभावना रखते हैं
    • इसलिए यह web apps के लिए tool है
  • अगर target सिर्फ एक language है, तो schema या code generation की जरूरत न होना स्वाभाविक है

  • tRPC को लगभग 50 हजार lines वाले दो web applications में इस्तेमाल किया और बहुत पसंद आया। developer experience शानदार है
    हालांकि tRPC का hype phase काफी पहले गुजर चुका है, और लगता है RSC का hype तेजी से उसके ऊपर आ गया
    आजकल tRPC जैसा stable और अच्छा solution होने के बावजूद सब बस यही बात करते हैं कि RSC इस्तेमाल करना है या नहीं
    मैं RSC के खिलाफ नहीं हूं, लेकिन discussion बहुत ज्यादा है। आजकल application बनाते समय tRPC बहुत practical तरीका है
    जोड़ा गया: RSC का मतलब React Server Components है, और यह read/write data की अपनी philosophy भी साथ लाता है

    • RSC के बारे में कभी नहीं सुना और search में भी आसानी से नहीं मिल रहा। link हो तो अच्छा होगा
    • Royal Shakespeare Company का RPC से क्या संबंध है, समझ नहीं आ रहा
      ऐसे acronyms जिन्हें लोग न जानते हों, उन्हें define कर देना या link जोड़ देना अच्छा होगा
  • कुछ निजी projects में tRPC और Next.js इस्तेमाल किया था, और अनुभव अच्छा रहा
    खासकर Create T3 App(https://create.t3.gg/) जैसे पहले से configured templates के साथ इस्तेमाल करें, तो iteration speed को मात देना मुश्किल है

    • जिज्ञासा है कि अब यह Next 13 और server components के साथ भी ठीक से काम करता है या नहीं
  • साथ काम करने वाले एक developer ने tRPC की खूब तारीफ़ की, उससे पहले मुझे इसके बारे में पता नहीं था; जानने के बाद यह बहुत साफ़ तौर पर अच्छा लगा
    हमने साथ में एक T3 app(tRPC, Next.js, Tailwind, TypeScript, Prisma) बनाया था, अगर देखना चाहें तो यहाँ है: https://github.com/stytchauth/stytch-t3-example
    TypeScript में काम करते समय type-safe API वाकई बहुत मददगार होती है