gRPC for JavaScript (Node.js): Libraries and Examples
gRPC is a high-performance remote procedure call (RPC) framework developed by Google. It uses Protocol Buffers (protobuf) for data serialization and HTTP/2 for transport. In the Node.js ecosystem, gRPC allows you to create fast and reliable microservices with support for bidirectional streaming. In this article, we will cover the main libraries, installation, and write a working example of a server and client.
Main Libraries for gRPC in Node.js
There are several key packages for working with gRPC in the Node.js environment:
@grpc/grpc-js— a pure JavaScript implementation of gRPC. It requires no native (C++) dependencies, simplifying installation. Recommended for most modern projects.@grpc/proto-loader— a loader for.protofiles. It converts protobuf definitions into JavaScript objects for use with@grpc/grpc-js.protobufjs— an alternative library for working with protobuf. It supports both static and dynamic code generation.grpc-tools— CLI tools for generating JavaScript code from.protofiles (an alternative to dynamic loading).
In this guide, we will use the combination of @grpc/grpc-js and @grpc/proto-loader — this is a modern and stable approach.
Installing Dependencies
Create a new project and install the necessary packages:
mkdir grpc-node-examplecd grpc-node-examplenpm init -ynpm install @grpc/grpc-js @grpc/proto-loaderDefining a Service via a .proto File
Create a file hello.proto with the service and message definitions:
syntax = "proto3";
service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} rpc SayHelloStream (HelloRequest) returns (stream HelloReply) {}}
message HelloRequest { string name = 1;}
message HelloReply { string message = 1;}Here we defined two methods: a simple unary SayHello and a server streaming SayHelloStream.
Implementing a gRPC Server in Node.js
Create a file server.js:
const grpc = require('@grpc/grpc-js');const protoLoader = require('@grpc/proto-loader');
const PROTO_PATH = './hello.proto';
// Load the proto file definitionconst packageDefinition = protoLoader.loadSync(PROTO_PATH, { keepCase: true, longs: String, enums: String, defaults: true, oneofs: true});
const helloProto = grpc.loadPackageDefinition(packageDefinition).helloworld;
// Implementation of service methodsfunction sayHello(call, callback) { const name = call.request.name; console.log(`Received request: ${name}`); callback(null, { message: `Hello, ${name}!` });}
function sayHelloStream(call) { const name = call.request.name; console.log(`Streaming for: ${name}`);
// Send multiple responses for (let i = 0; i < 5; i++) { call.write({ message: `Hello ${name} - message ${i + 1}` }); } call.end();}
// Start the serverfunction main() { const server = new grpc.Server(); server.addService(helloProto.Greeter.service, { sayHello: sayHello, sayHelloStream: sayHelloStream });
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => { console.log('gRPC server running on port 50051'); server.start(); });}
main();Implementing a gRPC Client in Node.js
Create a file client.js:
const grpc = require('@grpc/grpc-js');const protoLoader = require('@grpc/proto-loader');
const PROTO_PATH = './hello.proto';
const packageDefini