grpc-web: grpc-web not working in a Vite+Typescript app

I used protoc -I=. protos/*.proto --js_out=import_style=commonjs,binary:grpcproto_web/ --grpc-web_out=import_style=typescript,mode=grpcweb:grpcproto_web/ to generate my proto file.

Then whenever I try to import proto objects like import { LoginRequest } from '../protos/login_pb'; I get errors Uncaught SyntaxError: import not found: LoginRequest.

I looked at issues #535 or vite#3898 but nothing works.

Does anyone have a working example using Vite+Typescript with grpc-web ?

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 35
  • Comments: 39

Commits related to this issue

Most upvoted comments

I found the missing piece of the puzzle. When I add the following to my vite.config.js in the branch martinpokorny, it works now:

  resolve: {
      preserveSymlinks: true,
    } 

Are there any updates on this issue?

@loicmagne You can use @protobuf-ts and protoc --ts_out ./generated --proto_path "./proto" <protoFilesPaths> command. It works fine with Vite.

I created a working demo for this issue.

Vite apps cannot import CommonJS files (like generated grpc-web files) directly, but it is possible if we make those generated CommonJS files as a local dependency and import from that dep.

Details are in the repo. Too lazy to create the whole envoy proxy and grpc servers but I’m working on a project where grpc-web with vite successfully communicates with grpc servers, so I can assure you this is one way of doing this right.

https://github.com/a2not/vite-grpc-web

@sampajano is there any plan to fix grpc-web? I just used the command from the README.md for TypeScript:

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

But I don’t get generated the promissed _grpc_web_pb.ts file. Instead it generates a Pb file with some require('google-protobuf') which will not work on browser environment.

Thanks @FredrikMeyer, I read it above, but I thought that protobuf-ts is only for messages and must use grpc-web for RPC. Now I also use protobuf-ts for RPC and works perfectly. The key word is replace. Thanks again for mentioning it.

For anyone who came here looking for a solution, please read the protobuf-ts manual:

https://github.com/timostamm/protobuf-ts/blob/main/MANUAL.md

it works perfectly (provided that you have enabled grpc-web in the backend).

@a2not Aha no problem! Glad to hear! Thanks so much for helping creating the working demo! 😊 (And same with @boldt!)

I’ll update our doc in a bit (after i’m back from vacation) and point to the Vite example of yours, and the resolve this bug.

Happy Thanksgiving everyone! 😃

@sampajano oh, sorry for the typo. It’s now possible!

It’s not about grpc-web, but about how you use Vite properly in my opinion.

I had tried compiling using the typescript or commonjs and was not working. The missing step was the webpack. Same is being described even here https://github.com/vitejs/vite/discussions/8926 My colleagues are not happy to have webpack and vite on same repo so we will look for other ways.

One solution is the first solution here I am still curious how the first method on that link works. If someone could post an example package.json would be great. We will pack our protobuffers in an npm package as we do usually and will check one more time.

I think I may have gotten this to work and so am sharing what no longer throws the errors similar to the one mentioned by OP when using gRPC-Web and Vite/TypeScript - for me after running

protoc service.proto \
    --proto_path=. \
    --js_out=import_style=commonjs:. \
    --grpc-web_out=import_style=typescript,mode=grpcwebtext:.

importing the client type from the gRPC-Web generated file can be done using an import statement: import { Client } from './serviceServiceClientPb'; and then the entire service in the generated js / d.ts files is imported using a require statement: const service = require('./service_pb'); at which point the types of the service can be utilized as members of the service: var request = new service.Request(); The types from the service client generated file can be constructed as standalone types, e.g.: var client = new Client('[insert address here]');

Hope this is a helpful working solution for people looking to use gRPC-Web with Vite/Typescript!

@lbensaad I think the suggestion of @Krzysztof-Dziardziel is to replace grpc-web with protobuf-ts. That’s what we did at my job (and it works wonderfully - the objects are much easier to work with, they are just regular JS objects)

I’m having the same issue. Sadly, I couldn’t get it to work. I also wasn’t able to get Vite+JS to work. Looks like this is some issue with how Vite loads external resources. 😞

Thanks everyone for helping figuring this out! I’m closing this issue for now 😊

I personally think this is not grpc-web’s fault.

Whether or not grpc-web should support generation of ES Module files is for sure another topic to consider, because Vite and other tools and js community in general are leaning towards ESM rather than CJS. But we can discuss that in https://github.com/grpc/grpc-web/issues/535.

Yeah thanks for your opinion!

I agree that ES Module is how things should be done in today’s world and we’ll definitely consider modernizing towards that!

But it is not possible using grpc-web’s CJS with Vite, so I would say this issue can be resolved now 🤔

Do you mean this is now possible? 😃

@a2not Wow thanks for providing a working demo too! It’s great to hear that these working solutions exist now! 😃

Hey,

I created minimal (not) working examples: https://github.com/boldt/grpcweb-cra-to-vite

They show, that the provides solutions by @martinpokorny and @mvonwaldner do not work. I would like to invite @sampajano, @martinpokorny and @mvonwaldner to help us to get that MWEs work.

Probably I am just missing a small piece of the puzzle.

Works with the old CRA

https://github.com/boldt/grpcweb-cra-to-vite/tree/main

It works as expected.

Does not work: Solution by martinpokorny

@see comment from @martinpokorny: https://github.com/grpc/grpc-web/issues/1242#issuecomment-1731152138

https://github.com/boldt/grpcweb-cra-to-vite/tree/martinpokorny

It throws:

Uncaught SyntaxError: The requested module ‘/src/grpc/echo_pb.js’ does not provide an export named ‘EchoRequest’ (at App.tsx:4:10)

Does not work: Solution by mvonwaldner

@see comment from @mvonwaldner: https://github.com/vitejs/vite/discussions/8926#discussioncomment-7143295

https://github.com/boldt/grpcweb-cra-to-vite/tree/mvonwaldner

It throws:

Uncaught TypeError: service.EchoRequest is not a constructor

Hello i have been facing the same issue here, I solve it and I created a starter demo example for people also strugling with it. @Shegl maybe you can test it

https://github.com/Aymeric-Henry/GRPC-Vite-TS-Svelte

if you have commentary about it I open to criticism

@sampajano thanks, actually the rest of the documentation including the example do not work.

import {EchoServiceClient} from './echo_grpc_web_pb';

Should be then

import {EchoServiceClient} from './EchoServiceClientPb';

But also, there is a problem since when I run it in the browser I get the error: SyntaxError: import not found: EchoRequest (exactly same problem mentioned above).

Also the ts-example/client.ts does not match the documented code on README.md so it cannot be a full version of it.