Top Related Projects
The Go language implementation of gRPC. HTTP/2 based RPC
gRPC for Node.js
The Java gRPC implementation. HTTP/2 based RPC
Protocol Buffers - Google's data interchange format
gRPC Web implementation for Golang and TypeScript
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:
-
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.
-
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.
-
Implement the client-side logic:
- Import the generate
Competitor Comparisons
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.
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.
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.
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 designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
gRPC Web ·
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:
- Unary RPCs (example)
- Server-side Streaming RPCs (example) (NOTE: Only when
grpcwebtext
mode is used.)
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 byprotoc-gen-js
pluginhelloworld_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
andtypescript
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
typingsimport_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 forecho_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. formetadata
andstatus
) 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.
-
The current default proxy is Envoy, which supports gRPC-web out of the box.
$ docker-compose up -d node-server envoy commonjs-client
-
You can also try the gRPC-web Go proxy.
$ docker-compose up -d node-server grpcwebproxy binary-client
-
Apache APISIX has also added grpc-web support, and more details can be found here.
-
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
Top Related Projects
The Go language implementation of gRPC. HTTP/2 based RPC
gRPC for Node.js
The Java gRPC implementation. HTTP/2 based RPC
Protocol Buffers - Google's data interchange format
gRPC Web implementation for Golang and TypeScript
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.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot