gRPC for JavaScript (Node.js): libraries, setup, and code examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

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 reliable microservices with strong typing, streaming support, and bidirectional communication. In this article, we will review the main libraries for working with gRPC in JavaScript (Node.js) and walk through a practical server and client example.



Main libraries for gRPC in Node.js



Two main packages are used for working with gRPC in Node.js:



  • @grpc/grpc-js — a pure JavaScript implementation of gRPC. It requires no native dependencies, works on all platforms, and supports all gRPC features (unary calls, server and client streaming, bidirectional streaming).
  • @grpc/proto-loader — a utility for loading .proto files at runtime. It allows dynamically creating JavaScript objects from Protobuf definitions.


For compiling .proto files into static modules, you can use grpc-tools (part of grpc-tools), but in modern projects dynamic loading via @grpc/proto-loader is more commonly used.



Installing dependencies



npm install @grpc/grpc-js @grpc/proto-loader


Example: defining a Proto file



Let's create a helloworld.proto file with a simple service:



syntax = "proto3";

package helloworld;

service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {}}

message HelloRequest { string name = 1;}

message HelloReply { string message = 1;}


Server side (Node.js)



Let's create a server.js file:



const grpc = require('@grpc/grpc-js');const protoLoader = require('@grpc/proto-loader');const path = require('path');

const PROTO_PATH = path.join(__dirname, 'helloworld.proto');

const packageDefinition = protoLoader.loadSync(PROTO_PATH, { keepCase: true, longs: String, enums: String, defaults: true, oneofs: true});

const helloProto = grpc.loadPackageDefinition(packageDefinition).helloworld;

function sayHello(call, callback) { const name = call.request.name || 'Guest'; callback(null, { message: `Hello, ${name}!` });}

function main() { const server = new grpc.Server(); server.addService(helloProto.Greeter.service, { sayHello: sayHello }); server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => { console.log('gRPC server started on port 50051'); server.start(); });}

main();


Client side (Node.js)



Let's create a client.js file:



const grpc = require('@grpc/grpc-js');const protoLoader = require('@grpc/proto-loader');const path = require('path');

const PROTO_PATH = path.join(__dirname, 'helloworld.proto');

const packageDefinition = protoLoader.loadSync(PROTO_PATH, { keepCase: true, longs: String, enums: String, defaults: true, oneofs: true});

const helloProto = grpc.loadPackageDefinition(packageDefinition).helloworld;

function main() { const client = new helloProto.Greeter('localhost:50051', grpc.credentials.createInsecure());

const userName = process.argv[2] || 'World';

client.sayHello({ name: userName }, (error, response) => { if (error) { console.error('Error:', error.message); return; } console.log('Server response:', response.message); });}

main();


Running and testing



Start the server in one terminal:



node server.js


In another terminal, run the client:



node client.js Ivan


You should

Recommendations