Convert Figma logo to code with AI

grpc logogrpc-web

gRPC for Web Clients

8,558
762
8,558
205

Top Related Projects

20,846

The Go language implementation of gRPC. HTTP/2 based RPC

gRPC for Node.js

11,358

The Java gRPC implementation. HTTP/2 based RPC

65,113

Protocol Buffers - Google's data interchange format

gRPC Web implementation for Golang and TypeScript

9,794

Tars is a high-performance RPC framework based on name service and Tars protocol, also integrated administration platform, and implemented hosting-service via flexible schedule.

Quick Overview

The grpc/grpc-web repository is a set of client libraries that enable web applications to access gRPC services. It allows developers to build modern, high-performance, and scalable web applications using the gRPC protocol, which is typically used for communication between microservices.

Pros

  • Cross-Platform Compatibility: grpc-web provides client libraries for various web frameworks, including JavaScript, TypeScript, and Dart, making it accessible to a wide range of web development teams.
  • Performance Optimization: By leveraging the efficient binary protocol of gRPC, grpc-web can achieve better performance compared to traditional REST-based web services.
  • Seamless Integration: grpc-web integrates well with the existing gRPC ecosystem, allowing developers to reuse their existing gRPC service definitions and infrastructure.
  • Improved Developer Experience: The project provides a consistent and familiar development experience for web developers who are already familiar with gRPC.

Cons

  • Limited Browser Support: grpc-web requires the use of a proxy server to handle the communication between the browser and the gRPC server, which can add complexity to the deployment and configuration process.
  • Learning Curve: Developers who are new to gRPC may need to invest time in understanding the protocol and its differences from traditional web services.
  • Ecosystem Maturity: Compared to more established web service technologies, the grpc-web ecosystem is still relatively young and may have fewer resources and community support available.
  • Compatibility Challenges: Ensuring compatibility between the grpc-web client libraries and the gRPC server-side implementation can sometimes be a challenge, especially when dealing with different versions or custom extensions.

Code Examples

Here are a few code examples demonstrating the usage of grpc-web:

Example 1: Defining a gRPC Service

syntax = "proto3";

package helloworld;

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

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

Example 2: Generating the grpc-web Client

protoc -I=. --js_out=import_style=commonjs:. --grpc-web_out=import_style=commonjs,mode=grpcwebtext:. helloworld.proto

Example 3: Using the grpc-web Client in JavaScript

const {GreeterClient} = require('./helloworld_grpc_web_pb.js');
const {HelloRequest} = require('./helloworld_pb.js');

const client = new GreeterClient('http://localhost:8080');

const request = new HelloRequest();
request.setName('John');

client.sayHello(request, (err, response) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log(response.getMessage());
});

Example 4: Using the grpc-web Client in TypeScript

import { GreeterClient } from './helloworld_grpc_web_pb';
import { HelloRequest } from './helloworld_pb';

const client = new GreeterClient('http://localhost:8080');

const request = new HelloRequest();
request.setName('John');

client.sayHello(request, (err, response) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log(response.getMessage());
});

Getting Started

To get started with grpc-web, follow these steps:

  1. Install the necessary dependencies:

    • Install the grpc-web client library for your preferred language (e.g., JavaScript, TypeScript, Dart).
    • Set up a gRPC server that can handle the requests from the grpc-web client.
  2. Define your gRPC service using Protocol Buffers (.proto files):

    • Specify the service, methods, and message structures.
    • Generate the client and server code using the protoc compiler with the --grpc-web_out option.
  3. Implement the client-side logic:

    • Import the generate

Competitor Comparisons

20,846

The Go language implementation of gRPC. HTTP/2 based RPC

Pros of grpc-go

  • Native Go implementation, offering better performance and integration with Go ecosystem
  • More mature and feature-complete, supporting advanced gRPC features
  • Extensive documentation and community support

Cons of grpc-go

  • Limited to server-side and CLI applications, not suitable for browser-based clients
  • Steeper learning curve for developers new to Go or gRPC concepts

Code Comparison

grpc-go:

import "google.golang.org/grpc"

s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
s.Serve(lis)

grpc-web:

import { GreeterClient } from './greeter_grpc_web_pb';

const client = new GreeterClient('http://localhost:8080');
client.sayHello(request, {}, (err, response) => {
  // Handle response
});

Key Differences

  • grpc-go is designed for server-side Go applications, while grpc-web enables gRPC in web browsers
  • grpc-go offers full gRPC functionality, whereas grpc-web provides a subset tailored for web environments
  • grpc-web requires additional server-side proxy setup to work with existing gRPC servers

Both projects serve different purposes within the gRPC ecosystem, with grpc-go focusing on server-side implementations and grpc-web bridging the gap for browser-based clients.

gRPC for Node.js

Pros of grpc-node

  • Native Node.js implementation, offering better performance and integration with Node.js ecosystem
  • Supports both client and server-side gRPC implementations
  • More mature and feature-rich, with better support for advanced gRPC features

Cons of grpc-node

  • Limited to Node.js environments, not suitable for browser-based applications
  • Requires more setup and configuration compared to grpc-web
  • Steeper learning curve for developers new to gRPC concepts

Code Comparison

grpc-node:

const grpc = require('grpc');
const protoLoader = require('@grpc/proto-loader');
const packageDefinition = protoLoader.loadSync('path/to/proto/file.proto');
const grpcObject = grpc.loadPackageDefinition(packageDefinition);
const client = new grpcObject.ServiceName('localhost:50051', grpc.credentials.createInsecure());

grpc-web:

const {ServiceNameClient} = require('generated_grpc_pb.js');
const {ServiceRequest} = require('generated_pb.js');
const client = new ServiceNameClient('http://localhost:8080');
const request = new ServiceRequest();
client.methodName(request, {}, (err, response) => { /* handle response */ });

grpc-web is designed for browser environments, offering a simpler setup and integration with web applications. It provides a more accessible entry point for web developers to use gRPC, but with limited features compared to grpc-node. grpc-node, on the other hand, offers a more comprehensive gRPC experience for Node.js applications, with better performance and advanced feature support.

11,358

The Java gRPC implementation. HTTP/2 based RPC

Pros of grpc-java

  • Better performance and lower latency for server-side applications
  • Full support for all gRPC features, including streaming and advanced options
  • Seamless integration with Java ecosystem and existing Java projects

Cons of grpc-java

  • Limited browser support, primarily designed for server-side and Android
  • Steeper learning curve for developers new to gRPC concepts
  • Larger footprint and more complex setup compared to grpc-web

Code Comparison

grpc-java:

@Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
    HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
    responseObserver.onNext(reply);
    responseObserver.onCompleted();
}

grpc-web:

client.sayHello(request, {}, (err, response) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log(response.getMessage());
});

The grpc-java example shows a server-side implementation, while the grpc-web example demonstrates a client-side call. grpc-java offers more control and flexibility, whereas grpc-web provides a simpler API for browser-based applications.

65,113

Protocol Buffers - Google's data interchange format

Pros of protobuf

  • More versatile, supporting multiple programming languages and platforms
  • Smaller message size and faster serialization/deserialization
  • Mature ecosystem with extensive tooling and community support

Cons of protobuf

  • Steeper learning curve for developers new to the protocol buffer concept
  • Requires additional steps for schema definition and code generation
  • Less suitable for browser-based applications compared to grpc-web

Code Comparison

protobuf:

syntax = "proto3";

message Person {
  string name = 1;
  int32 age = 2;
}

grpc-web:

const {HelloRequest, HelloReply} = require('./helloworld_pb.js');
const {GreeterClient} = require('./helloworld_grpc_web_pb.js');

var client = new GreeterClient('http://localhost:8080');

var request = new HelloRequest();
request.setName('World');

protobuf is a language-agnostic data serialization format, while grpc-web is specifically designed for web clients to communicate with gRPC services. protobuf offers broader language support and efficient data encoding, making it suitable for various use cases. grpc-web, on the other hand, provides a more streamlined experience for web developers working with gRPC backends, simplifying the integration of gRPC in browser environments.

gRPC Web implementation for Golang and TypeScript

Pros of grpc-web

  • Pure TypeScript implementation, offering better type safety and integration with TypeScript projects
  • Supports bi-directional streaming, allowing for more advanced real-time communication
  • Works with standard gRPC servers without additional proxies or modifications

Cons of grpc-web

  • Less mature and less widely adopted compared to the official implementation
  • May have fewer resources and community support available
  • Potentially less stable or feature-complete in some areas

Code Comparison

grpc-web:

const { HelloRequest, HelloReply } = require('./helloworld_pb.js');
const { GreeterClient } = require('./helloworld_grpc_web_pb.js');

var client = new GreeterClient('http://localhost:8080');

var request = new HelloRequest();
request.setName('World');

client.sayHello(request, {}, (err, response) => {
  console.log(response.getMessage());
});

grpc-web:

import { grpc } from "@improbable-eng/grpc-web";
import { HelloRequest, HelloReply } from "./helloworld_pb";
import { Greeter } from "./helloworld_pb_service";

const client = grpc.client(Greeter.SayHello, {
  host: "http://localhost:8080",
});

client.start();
client.send(new HelloRequest().setName("World"));

client.onMessage((message: HelloReply) => {
  console.log(message.getMessage());
});

Both implementations offer similar functionality, but grpc-web uses TypeScript and provides a more modern, Promise-based API. The official grpc-web uses a callback-based approach and relies on generated JavaScript files.

9,794

Tars is a high-performance RPC framework based on name service and Tars protocol, also integrated administration platform, and implemented hosting-service via flexible schedule.

Pros of Tars

  • More comprehensive microservices framework with built-in service governance
  • Supports multiple programming languages (C++, Java, PHP, Node.js, etc.)
  • Includes features like service discovery, load balancing, and monitoring

Cons of Tars

  • Steeper learning curve due to its comprehensive nature
  • Less widespread adoption compared to gRPC-Web
  • May be overkill for simpler projects or smaller teams

Code Comparison

gRPC-Web:

const {HelloRequest} = require('./helloworld_pb.js');
const {GreeterClient} = require('./helloworld_grpc_web_pb.js');

var client = new GreeterClient('http://localhost:8080');

var request = new HelloRequest();
request.setName('World');

client.sayHello(request, {}, (err, response) => {
  console.log(response.getMessage());
});

Tars:

#include <servant/Application.h>
#include "HelloServant.h"

class HelloServer : public Application
{
protected:
    virtual void initialize() {
        addServant<HelloServantImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".HelloObj");
    }
};

int main(int argc, char* argv[])
{
    HelloServer app;
    return app.main(argc, argv);
}

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

gRPC Web · npm version

A JavaScript implementation of gRPC for browser clients. For more information, including a quick start, see the gRPC-web documentation.

gRPC-web clients connect to gRPC services via a special proxy; by default, gRPC-web uses Envoy.

In the future, we expect gRPC-web to be supported in language-specific web frameworks for languages such as Python, Java, and Node. For details, see the roadmap.

Streaming Support

gRPC-web currently supports 2 RPC modes:

Client-side and Bi-directional streaming is not currently supported (see streaming roadmap).

Quick Start

Eager to get started? Try the Hello World example. From this example, you'll learn how to do the following:

  • Define your service using protocol buffers
  • Implement a simple gRPC Service using NodeJS
  • Configure the Envoy proxy
  • Generate protobuf message classes and client service stub for the client
  • Compile all the JS dependencies into a static library that can be consumed by the browser easily

Advanced Demo: Browser Echo App

You can also try to run a more advanced Echo app from the browser with a streaming example.

From the repo root directory:

$ docker-compose pull prereqs node-server envoy commonjs-client
$ docker-compose up node-server envoy commonjs-client

Open a browser tab, and visit http://localhost:8081/echotest.html.

To shutdown: docker-compose down.

Runtime Library

The gRPC-web runtime library is available at npm:

$ npm i grpc-web

Code Generator Plugins

(Prerequisite) 1. Protobuf (protoc)

If you don't already have protoc installed, download it first from here and install it on your PATH.

If you use Homebrew (on macOS), you could run:

brew install protobuf

(Prerequisite) 2. Protobuf-javascript (protoc-gen-js)

If you don't have protoc-gen-js installed, download it from protocolbuffers/protobuf-javascript and install it on your PATH.

Or, use the third-party NPM installer:

npm install -g protoc-gen-js

3. Install gRPC-Web Code Generator

You can download the protoc-gen-grpc-web protoc plugin from our release page:

Make sure all executables are discoverable from your PATH.

For example, on MacOS, you can do:

sudo mv protoc-gen-grpc-web-1.5.0-darwin-aarch64 \
    /usr/local/bin/protoc-gen-grpc-web

chmod +x /usr/local/bin/protoc-gen-grpc-web

(Optional) 4. Verify Installations

You can optionally verify the plugins works follwoing our Hello world example:

cd net/grpc/gateway/examples/helloworld

protoc -I=. helloworld.proto \
  --js_out=import_style=commonjs:. \
  --grpc-web_out=import_style=commonjs,mode=grpcwebtext:.

After the command runs successfully, you should now see two new files generated in the current directory. By running:

ls -1 *_pb.js

Installation is successful if you see the following 2 files:

  • helloworld_pb.js # Generated by protoc-gen-js plugin
  • helloworld_grpc_web_pb.js - Generated by gRPC-Web plugin

Client Configuration Options

Typically, you will run the following command to generate the proto messages and the service client stub from your .proto definitions:

protoc -I=$DIR echo.proto \
  --js_out=import_style=commonjs:$OUT_DIR \
  --grpc-web_out=import_style=commonjs,mode=grpcwebtext:$OUT_DIR

You can then use Browserify, Webpack, Closure Compiler, etc. to resolve imports at compile time.

Import Style

import_style=closure: The default generated code has Closure goog.require() import style.

import_style=commonjs: The CommonJS style require() is also supported.

import_style=commonjs+dts: (Experimental) In addition to above, a .d.ts typings file will also be generated for the protobuf messages and service stub.

import_style=typescript: (Experimental) The service stub will be generated in TypeScript. See TypeScript Support below for information on how to generate TypeScript files.

Note: The commonjs+dts and typescript styles are only supported by --grpc-web_out=import_style=..., not by --js_out=import_style=....

Wire Format Mode

For more information about the gRPC-web wire format, see the specification.

mode=grpcwebtext: The default generated code sends the payload in the grpc-web-text format.

  • Content-type: application/grpc-web-text
  • Payload are base64-encoded.
  • Both unary and server streaming calls are supported.

mode=grpcweb: A binary protobuf format is also supported.

  • Content-type: application/grpc-web+proto
  • Payload are in the binary protobuf format.
  • Only unary calls are supported.

How It Works

Let's take a look at how gRPC-web works with a simple example. You can find out how to build, run and explore the example yourself in Build and Run the Echo Example.

1. Define your service

The first step when creating any gRPC service is to define it. Like all gRPC services, gRPC-web uses protocol buffers to define its RPC service methods and their message request and response types.

message EchoRequest {
  string message = 1;
}

...

service EchoService {
  rpc Echo(EchoRequest) returns (EchoResponse);

  rpc ServerStreamingEcho(ServerStreamingEchoRequest)
      returns (stream ServerStreamingEchoResponse);
}

2. Run the server and proxy

Next you need to have a gRPC server that implements the service interface and a gateway proxy that allows the client to connect to the server. Our example builds a simple Node gRPC backend server and the Envoy proxy.

For the Echo service: see the service implementations.

For the Envoy proxy: see the config yaml file.

3. Write your JS client

Once the server and gateway are up and running, you can start making gRPC calls from the browser!

Create your client:

var echoService = new proto.mypackage.EchoServiceClient(
  'http://localhost:8080');

Make a unary RPC call:

var request = new proto.mypackage.EchoRequest();
request.setMessage(msg);
var metadata = {'custom-header-1': 'value1'};
echoService.echo(request, metadata, function(err, response) {
  if (err) {
    console.log(err.code);
    console.log(err.message);
  } else {
    console.log(response.getMessage());
  }
});

Server-side streaming:

var stream = echoService.serverStreamingEcho(streamRequest, metadata);
stream.on('data', function(response) {
  console.log(response.getMessage());
});
stream.on('status', function(status) {
  console.log(status.code);
  console.log(status.details);
  console.log(status.metadata);
});
stream.on('end', function(end) {
  // stream end signal
});

// to close the stream
stream.cancel()

For an in-depth tutorial, see this page.

Setting Deadline

You can set a deadline for your RPC by setting a deadline header. The value should be a Unix timestamp, in milliseconds.

var deadline = new Date();
deadline.setSeconds(deadline.getSeconds() + 1);

client.sayHelloAfterDelay(request, {deadline: deadline.getTime().toString()},
  (err, response) => {
    // err will be populated if the RPC exceeds the deadline
    ...
  });

TypeScript Support

The grpc-web module can now be imported as a TypeScript module. This is currently an experimental feature. Any feedback welcome!

When using the protoc-gen-grpc-web protoc plugin, mentioned above, pass in either:

  • import_style=commonjs+dts: existing CommonJS style stub + .d.ts typings
  • import_style=typescript: full TypeScript output

Do not use import_style=typescript for --js_out, it will silently be ignored. Instead you should use --js_out=import_style=commonjs, or --js_out=import_style=commonjs,binary if you are using mode=grpcweb. The --js_out plugin will generate JavaScript code (echo_pb.js), and the -grpc-web_out plugin will generate a TypeScript definition file for it (echo_pb.d.ts). This is a temporary hack until the --js_out supports TypeScript itself.

For example, this is the command you should use to generate TypeScript code using the binary wire format

protoc -I=$DIR echo.proto \
  --js_out=import_style=commonjs,binary:$OUT_DIR \
  --grpc-web_out=import_style=typescript,mode=grpcweb:$OUT_DIR

It will generate the following files:

  • EchoServiceClientPb.ts - Generated by --grpc-web_out, contains the TypeScript gRPC-web code.
  • echo_pb.js - Generated by --js_out, contains the JavaScript Protobuf code.
  • echo_pb.d.ts - Generated by --grpc-web_out, contains TypeScript definitions for echo_pb.js.

Using Callbacks

import * as grpcWeb from 'grpc-web';
import {EchoServiceClient} from './EchoServiceClientPb';
import {EchoRequest, EchoResponse} from './echo_pb';

const echoService = new EchoServiceClient('http://localhost:8080', null, null);

const request = new EchoRequest();
request.setMessage('Hello World!');

const call = echoService.echo(request, {'custom-header-1': 'value1'},
  (err: grpcWeb.RpcError, response: EchoResponse) => {
    console.log(response.getMessage());
  });
call.on('status', (status: grpcWeb.Status) => {
  // ...
});

(See here full list of possible .on(...) callbacks)

(Option) Using Promises (Limited features)

NOTE: It is not possible to access the .on(...) callbacks (e.g. for metadata and status) when Promise is used.

// Create a Promise client instead
const echoService = new EchoServicePromiseClient('http://localhost:8080', null, null);

... (same as above)

this.echoService.echo(request, {'custom-header-1': 'value1'})
  .then((response: EchoResponse) => {
    console.log(`Received response: ${response.getMessage()}`);
  }).catch((err: grpcWeb.RpcError) => {
    console.log(`Received error: ${err.code}, ${err.message}`);
  });

For the full TypeScript example, see ts-example/client.ts with the instructions to run.

Custom Interceptors

Custom interceptors can be implemented and chained, which could be useful for features like auth, retries, etc.

There are 2 types of interceptors (interfaces):

  • UnaryInterceptor (doc, example) - Intercept Unary RPCs; can only be used with Promise clients.
  • StreamInterceptor (doc, example) - More versatile; can be used with regular clients.

For more details, see this blog post.

Ecosystem

Proxy Interoperability

Multiple proxies support the gRPC-web protocol.

  1. The current default proxy is Envoy, which supports gRPC-web out of the box.

    $ docker-compose up -d node-server envoy commonjs-client
    
  2. You can also try the gRPC-web Go proxy.

    $ docker-compose up -d node-server grpcwebproxy binary-client
    
  3. Apache APISIX has also added grpc-web support, and more details can be found here.

  4. Nginx has a grpc-web module (doc, announcement)), and seems to work with simple configs, according to user feedback.

Server Frameworks with gRPC-Web support

Web Frameworks Compatibility

NPM DownloadsLast 30 Days