RocketRPC: Simplifying Client-Server Interactions using TypeScript

RocketRPC is a framework that allows developers to invoke server functions on the client-side as if they were present on the client itself. In this article, we will discuss how we can use it, and how it works under the hood.

RocketRPC: Simplifying Client-Server Interactions using TypeScript

Have you ever dreamed of invoking server functions on the client-side as if they were present on the client itself? Imagine if this was as easy as writing a few lines of code and directly invoking the functions in the client for your desired result. This concept is similar to Remote Procedure Calls (RPC), but it goes beyond that. With RocketRPC, developers can seamlessly invoke server functions as if they were present on the client.

To watch the complete talk on YouTube instead, click on the video below

RocketRPC is a lightweight, easy-to-use, and open-source framework that simplifies server function invocations on the client-side. This framework allows developers to share types between the client and the server, which means that once the server builds a function, it can be shared directly with the client. Additionally, the code is self-documenting, as the types themselves have information on the function's input data, perform necessary data validation, and know what output the function will return.

Why RocketRPC?

RocketRPC was built to make server function invocations on the client-side simple and efficient. All of the communication happens over websockets, making the communication instantaneous, and preventing the need for batching requests, or making any other optimizations to HTTP.

Unlike other RPC libraries, there's no need for defining a router or any other boilerplate code for your method, making the experience of write functions truly native. RocketRPC also allows you to expose any server-side objects to the client. This could be an ORM object, your Prisma client, or any other object which can help speed up your application development process.

In this way, RocketRPC reduces the development time for web applications, improves performance, and reduces the number of requests sent to the server.

Using RocketRPC

Using RocketRPC is simple. Firstly, you need to install RocketRPC using your favorite Node package manager. If you use npm, run the following command:

npm i rocketrpc

Then, on the server-side, you can create a function that you want to invoke on the client-side. In this example, let's create a method - sum - which returns the sum of 2 numbers. Additionally, we can expose our prisma client over-the-wire as well.

import { Server } from "rocketrpc";
import { PrismaClient } from "@prisma/client";

// create the required method and object
const api = {
  // initialize Prisma once
  prisma: new PrismaClient();

  sum: (x: number, y: number) => x + y,
};

// export the type for inference on the client
export type API = typeof api;

Server(8080, api);

Reference link: https://github.com/akash-joshi/rocketrpc#server

Finally, on the client-side, you can directly call the function as if it were present on the client-side.

import { Client } from "rocketrpc";
import { API } from "../server";

const client = Client<API>("http://localhost:8080");

const { listFiles, prisma } = client;

const main = async () => {
  // use prisma on the client
  console.log(await prisma.user.findMany());

  // passing multiple parameters to the function
  console.log(await client.sum(12, 20));
};

main();

Reference link: https://github.com/akash-joshi/rocketrpc#client

And, to run the files - you just run them as normal :)

# on one terminal
ts-node-dev server.ts

# on a separate terminal
ts-node-dev client.ts

How it Works

Now, let's talk about some of the underlying technologies which make RocketRPC tick.

1. Websockets

One of the first decisions made in building RocketRPC was which networking tool to choose. Websockets were identified as the ideal choice for the framework since all functions reside on the server and require constant communication between the server and the client. Websockets are lightweight and do not require establishing a complete request payload for every connection, unlike HTTP requests that perform a handshake and require sending the complete request payload.

According to benchmarks, websockets can be faster than HTTP requests in cases where constant communication is required between the client and server. In this case, I chose Socket.IO as the networking library for RocketRPC since it provides an easy-to-use and powerful API for bidirectional communication between the server and the client. It also falls back to HTTP in case websockets are disabled.

2. Object Proxies

One of the biggest challenges in building RocketRPC was how to make the client aware of the server-side functions. Object Proxies, a feature provided by JavaScript, came to the rescue. Object Proxies are user-defined objects that allow developers to control all aspects of an object, including writing setters, getters, and more.

In RocketRPC, the get operation on objects is handled using Object Proxies. When a function is called on the client object, the invoked function name and all the passed parameters are sent to the server over websockets. The server then computes the result based on the parameters, and returns the response or any errors to the client.

3. Typescript generics

RocketRPC also allows for sharing types between the client and the server, making the code self-documenting. The types themselves provide information on the data that the function takes as input, perform data validation, and know what output the function will return.

Typescript generics were used to share types between the client and the server, while allowing the library to modify the types into the correct type. All methods are transformed to return promises, as the response is returned over the network. Anything on the API object which isn't a method is returned as never, as they are inaccessible from the client.

Conclusion

RocketRPC simplifies server function invocations on the client-side and reduces the development time for web applications. By using websockets and Object Proxies, RocketRPC enables developers to share types between the client and the server, making code self-documenting, and reducing the number of requests sent to the server. Try RocketRPC today and see how it can streamline your web application development process.