It can sometimes be difficult to understand how a new tool fits in your existing toolchain. How is it used with another framework? Does it replace other libraries? What is the difference between them? Let’s look through some popular tools today so that we can better understand what Prim+RPC is and how it can be used.
This page is not comprehensive and aims only to provide a high-level overview.
GraphQL is a form of RPC with its own querying language and types. It is a specification implemented in many programming languages and frameworks. It defines several operations to interact with data: queries to retrieve data, mutations to change data, and subscriptions to react to events on the server.
As a high-level overview, here is a summary of notable differences:
|Types defined using their SDL||Existing types (TypeScript/JSDoc) are utilized|
|Validation based on types||Validation is provided by developer|
|Provides queries to get data||Function call retrieves data|
|Provides mutations to change data||Function call changes data|
|Server updates given as subscriptions||Callbacks on functions receives server updates|
|Files uploads given by community-provided specification||Files can be passed to function|
|File downloads unsupported||Files can be returned from function|
Both libraries have features such as custom serialization, batching support, ability to “subscribe” to server updates, ability to pass server context to RPC library, among other features. A summary of notable differences:
|Generally intended for HTTP but can be used elsewhere||Transport agnostic but supports HTTP|
|Uses queries and mutations defined on a router||Uses functions defined a module|
|Uses subscriptions for server updates||Callbacks on functions receive server updates|
|Does not yet support file uploads or downloads||Files can be passed to and returned from function|
Data loaders is a concept that’s become popular with fullstack frameworks like Qwik, Next.js, Remix, and others. It is auto-generated RPC, created as part of a compile step, allowing server-side code to be written inside of and extracted from client-side code. This is generally used to transform data only available on the server into a format expected by UI components on the client but could potentially be used to create a client-specific API.
Prim+RPC auto-generates RPC as well but requests are inferred at runtime, without a compilation step. Server-side code is intended to be written separately from client-side code, by design. Since RPC is not extracted from code, there is no auto-generation of function names or routes: they are given by the name of your functions. There is also less risk of accidentally exposing server-side code to the client since client and server are separate and only types are shared.
As for how they may fit together: Prim+RPC is intended to write a full server API while data loaders are commonly used to transform data from a server’s API into a format expected by the client.
|RPC created during compilation||RPC inferred at runtime|
|Usually used to transform data from API to UI||Used to create a full server API|
|Server code exists inside of client code||Server and client are separate|
|Server utilities specific to given framework||Works with server of your choice|
|Type support limited to those given in framework||Type support can be extended with custom JSON handler|
gRPC is a form of RPC based around Protocol Buffers (“protobufs”) designed to work with many languages by creating a schema and implementing that schema with the server of your choice and connecting to the server with a compiled client which can be used in various programming languages. It provides many transport options such as unary, server-side, client-side, and bidirectional streaming, and has options for authentication.
|Server implements given specification||No specification required, inferred from module|
|Unary streaming||Function call|
|Server-side streaming||Callbacks on functions|
|Client-side and bidirectional streaming||No comparable options|
JSON RPC is an RPC specification based on JSON. It is a lightweight protocol and implementations vary widely. There are many implementations available in many languages but the underlying specification is fairly simple. It allows methods to be called and results received as either a result or an error. It also includes an option for batching requests. Many implementations support these basic features and may add additional features.
Prim+RPC supports all of JSON RPC’s features and many more. While the underlying RPC structures appear similar, Prim+RPC is not based on JSON RPC and covers features that don’t have equivalents in JSON RPC like callback support and file uploads. It has one implementation and it is both runtime and framework agnostic.
|Many implementations available||One implementation, framework-agnostic|
|Supports JSON types only||Serialization library can be swapped out|
|No file support officially||Files can be uploaded and downloaded with plugins|