question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[RFC] Next major overview

See original GitHub issue

So. We’re making a new major.

Goals

  • More ergonomic API for creating procedures and building out your backend
  • CMD+Click from your frontend and jump straight into the backend procedure. This will work with react-query as well!
  • Better scaling than the current structure - the TypeScript server starts choking a bit when you get close to 100 procedures in your backend
  • Fully backward compatible for the 99% use-case with a migration path which you can do incrementally.

Todos

Important for contributors: All of the work here is related to the next branch.

Tracked in https://github.com/orgs/trpc/projects/1

  • New Router API
    • Tracked in trpc/v10-playground - the current winning proposal is https://github.com/trpc/v10-playground/pull/33
    • Error formatting in new API - formatError()-equivalent.
    • meta-equivalent
    • Maybe we need a createRootRouter() that additionally accepts { transformer: X, formatError: Y}
    • Implement new API in tRPC
    • Make old routers compatible (.legacy() at the end to transform them to the new version)
  • New client API with backward compatibility
    • Maybe old can be client.query('postById', input, options) whilst new stuff can be client.queries.postById({ input, ...options})
  • New react-query API with backward compat
  • Make actual issues for all of these
  • Add all old projects in a folder (copy/paste examples/* to examples/.test so we can track breaking changes easily and make sure we remain backward compatible for a long time
  • Rewrite TRPCClient to be functional instead of a class but reuse the same interface
  • Write a migration guide
    • New router API
    • New links
  • Move transformers back to runtime to make it backward compatible
  • Explore: Add stripInternal-flag
  • Simplify HTTP-responses
  • New links architecture (#1366)
  • Refactor observables implementation to have unknown errors or make it guaranteed to be TRPCClientError of some sort.
  • Make transformers dynamically opt-in similar to how a batch request is indicated by ?batch=1 maybe a transformed request could be ?transform=1 or transform=TRANSFORMER_NAME?
  • Write a blog post about new major and API.
  • “Marketing”? Hype video, new website, etc
  • Decide on structure for react-query integration
  • Add old website on www/-docs as v9.trpc.io
    • Link it in Docusaurus
    • Make sure we have deployment for a “v9”-branch

Stretch

Old notes

Definite

  • Remove official support for node 12.x
    • Remove E2E-test for 12.x
    • Change tsconfig build target
  • Add official support for node 16.x
  • Add stripInternal-flag
  • Remove all @deprecated stuff
    • Remove LegacyRouter introduced in #915
    • […]
  • New links architecture (#1366)
  • Move official support for react-query 3 to 4
  • Simplify HTTP-responses
    • From { id:null, result: {type: 'data', data: x } } -> { result: { data: x } }
    • maybe remove id: null from HTTP responses?
  • Migration guides for all changed parts
    • New Links

Maybe ❓

Feedback please!

  • Optimize so router inference only needs to be done once? #1218
  • ~Update so procedures needs to return { data: x } instead of just x so we could add metadata and potentially discriminated union of { data: x } | { error: y } ~
  • Decide:
    • Pipe-based rather than object resolvers? { input: z.string(), resolve({input}) {}} -> `t.pipe(t.input(z.string), ({input}) =>
    • Chained resolvers
  • Plan how to deal with degrading typescript performance when approaching ~100 procedures (there are no runtime issues, but the DX slows down)
  • Turn client.query result into [ output, { meta } ]
  • New useQuery() API that expects suspense as default - See this gist: https://gist.github.com/KATT/aa1ad532d6e57520b942f657569e1505
  • Refactor @trpc/server to easier work with CloudFlare-workers etc (#1375)
  • Collaborate with Blitz.js? https://github.com/blitz-js/blitz/discussions/3083#discussioncomment-1841427
  • https://jsonapi.org/format/

Transformers

  • Turn transformers into a link on the client (#1366)
  • Revert above and put transformers back to runtime 😬
  • ~Turn transformers into a middleware on the server~
  • Make transformers dynamically opt-in similar to how a batch request is indicated by ?batch=1 maybe a transformed request could be ?transform=1 or transform=TRANSFORMER_NAME?

Misc

  • Rename @trpc/react/ssg -> @trpc/react/ssr & createSSGHelpers -> createServerSideHelpers (or something, as it is often used in getServerSideProps() as well as getStaticProps())

Open questions

  • Should we continue to follow OpenRPC?
  • Any changes that could make tRPC easier to support stuff like Svelte/Vue?
  • Any changes that could make tRPC stricter support stuff like AWS Lambdas? (Already is doable to do Lambdas but through an Express->Lambda converter) #882
  • Ideas?

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

10reactions
rakeshpaicommented, Aug 1, 2022

Hey. Just came across this upcoming update. I wasn’t aware that this update was in the works, and had started work on a similar project. https://github.com/rakeshpai/birdsong It isn’t production-ready yet. It is heavily inspired by tRPC, but these are the differences from tRPC 9:

  • Using actual tokens instead of strings to name methods (tRPC 10 takes care of this.)
  • Cmd+click to jump to definition between client and server. (Again, 10 takes care of this.)
  • Handling all the built-in JS types, eg. Dates, Maps, Sets, etc., and not just the primitives that JSON supports, without needing an external library. (tRPC requires an external library for this, but that might be ok for most people.)
  • Easily extending the supported types by writing simple serialiser / deserialiser functions for the new custom types - useful for custom types that don’t have internal state, like for eg. Email. (I haven’t exposed this currently even in my package, but the design has been done to allow for this.)
  • Being agnostic to the environment (node / deno / CF workers, etc) that the server is going to run in. This has been done by converting node’s request and response objects to W3C Request and Response objects at the boundaries, and using the W3C objects everywhere in the code rather than the node built-ins.
  • Automatically detecting if a method’s network call should be a GET or a POST rather than explicitly having to specify if the method is a query or a mutation - this has been done by seeing if the method name starts with some known prefixes like get or list. So, getUsers would be a GET request, and updateUser would be a POST just because of how they’re named. I’m on the fence about whether this is a good idea. It does simplify the API somewhat, but introduces a little bit of magic and/or forces a convention.
  • Keeping the client-side bundle vanishingly small - it’s currently under 5kb before minification and gzip, and IIRC it’s under 3kb after minification and gzip. (Aren’t proxies magical!) This does forgo many runtime checks, but that should be ok since the TS types are very strict.
  • A functional composition based API, rather than a chaining+router API, for writing the server code. You could put this down to personal preference - a chaining API might be what most people prefer anyway.
  • Simplified imports - there’s just one package to be npm installed, and the server and client code are both part of the same package. Client-side bundling + tree-shaking eliminates server code, so there’s no leakage of server code into the client bundle.
  • Built-in but opt-in pretty logging on the client-side similar to redux-logger to help with debugging.

I had even more ambitious plans with my package, but some of those have fallen by the wayside for now:

  • Having the same API for communication between the browser main thread and web workers to enable functionality similar to Comlink. The API has been designed to minimise HTTP-specifics to enable this in the future, but I haven’t done anything to actually build this out. The end result is that in large client-heavy projects, there’s only one RPC API that teams need to learn, regardless of which thread/network boundary they’re crossing.
  • Ditto for communication between the main thread and service workers. This is particularly interesting since the semantics are still of making HTTP calls from the main thread, except you run the ‘server’ inside a service worker. This could potentially open up the doors to building new kinds of apps that run primarily in the service worker, but are painful to do today because of how the sw APIs are. Again, I haven’t really explored this yet.

I’m very happy to know that the first two points above, which are the biggest ergonomic differences from tRPC 9, are now going to be handled in 10. With that in mind, I’m happy to abandon my project. However, I thought I’d leave the rest of the list here to see if there’s interest in targeting them with upcoming updates to tRPC.

You can see usage examples of my package in the tests. Apologies for not documenting this better.

Edit: Terminology (/s/module/package)

6reactions
sachinrajacommented, Aug 1, 2022

Hey @rakeshpai! Birdsong looks great! Here’s a response to your points:

Handling all the built-in JS types

I don’t see this changing for us. superjson handles all of this as you noted and allows you to have custom types with serializer/deserializer functions.

Being agnostic to the environment (node / deno / CF workers, etc) that the server is going to run in

tRPC v10 can run anywhere and is agnostic to the environment. We cannot use the Fetch API Request and Response yet because they aren’t available in Node so we just use a common format for request/response shapes. Also tRPC v10 has a Fetch adapter to convert these shapes to Request/Response objects.

Automatically detecting if a method’s network call should be a GET or a POST rather than explicitly having to specify if the method is a query or a mutation - this has been done by seeing if the method name starts with some known prefixes like get or list

We can consider this, but I don’t think it’s a great idea. I’m not a fan of implicit behavior on this level. In a way, having to specify keywords in front of the procedure names is still explicit. As a side note this was also brought up in https://github.com/trpc/trpc/discussions/2270#discussioncomment-3198442.

Keeping the client-side bundle vanishingly small

We’d love to have your help here! This is something on our radar to look at before release. That being said, the client is kept fairly minimal.

Simplified imports - there’s just one package to be npm installed

Yeah, this is also something we discussed. It’s not a huge problem right now (compared to the other things we’re working on), but we’re open to ideas here.

Built-in but opt-in pretty logging on the client-side

Awesome! tRPC has this too with the loggerLink.

Having the same API for communication between the browser main thread and web workers to enable functionality similar to Comlink. The API has been designed to minimise HTTP-specifics to enable this in the future, but I haven’t done anything to actually build this out.

You can likely achieve this with a custom link on the client. tRPC has also also been designed to minimize HTTP-specifics. For example, see the WebSocket link and trpc-chrome.


It seems like you’ve thought about this a lot and we’d love to have you involved in the decision-making for v10. We’d also love to have you as a contributor to tRPC! If you’re interested, please join the Discord and we can talk more.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Next.js Layouts RFC in 5 minutes - Vercel
The RFC is detailed and covers both basic and advanced features. This post will cover the most important features of the upcoming Next....
Read more >
Overview of Request For Change (RFC) Review Process
Overview of the process the Change Coordinator and the Change Review Board (CRB) follow for acting on Request for Changes (RFCs), based on...
Read more >
RFC 3780 - SMIng - Next Generation Structure of ...
SMIng - Next Generation Structure of Management Information (RFC 3780, ... Section 2 gives an overview of the basic concepts of data modeling...
Read more >
Next.js biggest change ever - YouTube
Next.js released Layouts RFC that could be gamechanger. Read more about it here: https://nextjs.org/blog/layouts- rfc ⚛️ Do you want to ...
Read more >
RFC process | Gatsby
The RFC process is a great opportunity to get more eyeballs on your proposal before it becomes a part of a released version...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found