gRPC-Web Client Runtime Library
grpc-web is the JavaScript client runtime library that enables browser-based applications to communicate with gRPC services. It functions by connecting to gRPC services through a specialized gateway proxy, such as Envoy, which has built-in gRPC-Web support. The current stable version is 2.0.2, with recent releases addressing bug fixes and minor improvements, including TypeScript compatibility updates. The project maintains a steady release cadence for bug fixes and incremental features. Key differentiators include its focus on browser environments, robust TypeScript support for generated client stubs, and the reliance on `protoc` and `protoc-gen-grpc-web` for generating client code and message definitions from `.proto` files, providing a full-stack gRPC experience for web clients.
Common errors
-
protoc-gen-grpc-web: program not found or is not executable
cause The `protoc-gen-grpc-web` plugin is either not installed, not in the system's PATH, or lacks execute permissions.fixDownload `protoc-gen-grpc-web` from the GitHub releases page, place it in a directory included in your system's PATH, and ensure it has execute permissions (e.g., `chmod +x protoc-gen-grpc-web`). -
TypeError: Cannot read properties of undefined (reading 'ClientReadableStream')
cause This often indicates that the `grpc-web` runtime library is not correctly imported or bundled, or that the generated client stub is trying to access `grpc.web` properties that are not available.fixEnsure `import * as grpcWeb from 'grpc-web';` is present and that your bundling tool (webpack, Parcel, Rollup) correctly includes the `grpc-web` library in your final output. Verify your `protoc-gen-grpc-web` output options match your project's module system (CommonJS/ESM). -
CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
cause The gRPC-Web proxy (e.g., Envoy) or the backend server is not correctly configured to handle Cross-Origin Resource Sharing (CORS) preflight requests from your web application's origin.fixConfigure your gRPC-Web proxy (e.g., Envoy's CORS filter) to include the `Access-Control-Allow-Origin` header with the appropriate value (e.g., your frontend's URL or `*` for development) and allow necessary HTTP methods (POST, OPTIONS) and headers.
Warnings
- breaking Enums generated for TypeScript versions older than 5.9 might encounter compatibility issues, leading to compilation errors or unexpected runtime behavior.
- gotcha gRPC-Web clients cannot directly connect to standard gRPC servers. An intermediary proxy (e.g., Envoy, or a gRPC-Web enabled Node.js proxy) is strictly required to translate between the gRPC-Web protocol used by browsers and the HTTP/2 gRPC protocol used by servers.
- gotcha Generating client stubs and message definitions requires both `protoc` (Protocol Buffers compiler) and `protoc-gen-grpc-web` (gRPC-Web plugin) to be installed and accessible in your system's PATH. Incorrect versions or missing executables will lead to generation failures.
- gotcha When generating TypeScript client stubs, choosing `import_style=commonjs+dts` provides CommonJS-style JavaScript files with separate `.d.ts` declaration files, while `import_style=typescript` provides full TypeScript output. Mixing these or using an inappropriate style can lead to import errors or type mismatches.
Install
-
npm install grpc-web -
yarn add grpc-web -
pnpm add grpc-web
Imports
- EchoServiceClient
const {EchoServiceClient} = require('./generated/echo_grpc_web_pb.js');import {EchoServiceClient} from './generated/echo_grpc_web_pb'; - EchoRequest
const {EchoRequest} = require('./generated/echo_pb.js');import {EchoRequest} from './generated/echo_pb'; - grpcWeb
import { GrpcWebClient } from 'grpc-web';import * as grpcWeb from 'grpc-web';
- RpcError
import * as grpcWeb from 'grpc-web'; /* ... */ (err: grpcWeb.RpcError) => { /* ... */ }
Quickstart
import * as grpcWeb from 'grpc-web';
import { EchoServiceClient } from './generated/echo_grpc_web_pb';
import { EchoRequest, EchoResponse } from './generated/echo_pb';
// Ensure you have a gRPC-Web proxy (e.g., Envoy) running at this address
const GRPC_PROXY_ADDRESS = 'http://localhost:8080';
// Create a client instance for your gRPC service
const echoService = new EchoServiceClient(GRPC_PROXY_ADDRESS, null, null);
// Create a new request message
const request = new EchoRequest();
request.setMessage('Hello from gRPC-Web!');
// Define custom metadata (optional)
const metadata = { 'custom-header-1': 'value1' };
// Make the gRPC call
const call = echoService.echo(
request,
metadata,
(err: grpcWeb.RpcError, response: EchoResponse) => {
if (err) {
console.error('Error during gRPC call:', err.code, err.message);
return;
}
console.log('Received message:', response.getMessage());
}
);
// Handle status updates (optional, for streaming or status monitoring)
call.on('status', (status: grpcWeb.Status) => {
if (status.code !== grpcWeb.StatusCode.OK) {
console.warn('gRPC call status:', status.code, status.details);
} else {
console.info('gRPC call completed successfully.');
}
});
// Handle stream errors (for server streaming, optional)
call.on('error', (err: grpcWeb.RpcError) => {
console.error('Stream error:', err.message);
});