grpc-web icon indicating copy to clipboard operation
grpc-web copied to clipboard

grpc-web not working in a Vite+Typescript app

Open loicmagne opened this issue 2 years ago • 2 comments

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 ?

loicmagne avatar May 11 '22 20:05 loicmagne

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. 😞

Krzysztof-Dziardziel avatar May 16 '22 07:05 Krzysztof-Dziardziel

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

Krzysztof-Dziardziel avatar May 31 '22 09:05 Krzysztof-Dziardziel

@Krzysztof-Dziardziel Could you please tell us how you configured protobuf-ts and grpc-web to work with vite?

lbensaad avatar Oct 09 '22 12:10 lbensaad

@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)

FredrikMeyer avatar Oct 13 '22 08:10 FredrikMeyer

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

This is best answer. We replace grpc-web with protobuf-ts, and every problem have been solved.

wirekang avatar Oct 17 '22 02:10 wirekang

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.

lbensaad avatar Oct 26 '22 07:10 lbensaad

@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.

barrelful avatar Jan 16 '23 10:01 barrelful

@lbensaad @FredrikMeyer when replacing gprc-web with protobuf-ts are you using @protobuf-ts/grpcweb-transport? Did you manage do receive a stream with it?

I am having Not Found error for POST http://localhost:5173/0.0.0.0:8080/my_proto.Haberdashery/MakeRowOfHats the example below:

service Haberdashery {
    rpc MakeRowOfHats (Size) returns (stream Hat);
}

staticdev avatar Jan 16 '23 21:01 staticdev

@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.

@barrelful Thanks for reporting the issue!

FYI the documentation was wrong. There is a generated TS file but with a different name than what's documented. :)

I've fixed it in #1314 above. Let me know there's more blocking issues for you. Thanks!

sampajano avatar Jan 19 '23 23:01 sampajano

@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.

barrelful avatar Jan 22 '23 16:01 barrelful

@barrelful this makes this lib unusable by me, once it is fixed I will try again.

staticdev avatar Feb 05 '23 14:02 staticdev

@barrelful Thanks for pointing out the typo, will fix the documentation. :)

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.

I'm guessing that you could be missing a webpack step as we usually intend to have. Please see the below steps for more details on how to run ts-example/client.ts.


@barrelful @staticdev The Typescript example works for me using the new instructions added below:

https://github.com/grpc/grpc-web/tree/master/net/grpc/gateway/examples/echo/ts-example/README.md

Please let me know if the above works for you and if you run into any issues.

Thanks!

sampajano avatar Feb 07 '23 23:02 sampajano

@sampajano thanks for updating the docs. Still the problem is NOT in the import EchoServiceClient anymore but in the following imports

If you run it as Vite application you will get:

Uncaught SyntaxError: import not found: EchoRequest

On the IDE also nothing is found:

 './echo_pb' has no exported member 'EchoRequest'
 './echo_pb' has no exported member 'EchoResponse'
 './echo_pb' has no exported member 'ServerStreamingEchoRequest'
 './echo_pb' has no exported member 'ServerStreamingEchoResponse'

Another confusing thing is that in the new docs you added recommends using mode=grpcwebtext, but on root README.md it has mode=grpcweb. In any case, I tried both and the errors are always the same.

barrelful avatar Feb 10 '23 17:02 barrelful

That is true @barrelful, it is not a problem of the documentation I would say. I had the same frustrating experience and decided to go back to good old REST APIs. Maybe if there is a bugfix by @sampajano or other core developers I will be able to try again and give feedback. Unfortunately I could not understand the code well enough to contribute and would require much greater amount of effort on my side.

catarse-natural avatar Feb 10 '23 18:02 catarse-natural

@barrelful @catarse-natural thanks for the feedbacks..

@barrelful I'm guessing the issue is Vite specific, is that right? I'm not really familiar with the framework, so i can't really comment on why this is happening..

If you could take a look at your setup v.s. the one i mentioned in the documentation, maybe you can identify what exactly is different (e.g. runtime, different JS bundler (we used WebPack in the example), etc.), and maybe that would give a hint on the nature of this issue..

thanks :)

sampajano avatar Feb 10 '23 22:02 sampajano

@sampajano I spent hours more testing, tried all combinations of --js_out=import_style=commonjs,binary and --js_out=import_style=commonjs, with --grpc-web_out=import_style=typescript,mode=grpcweb and --grpc-web_out=import_style=typescript,mode=grpcwebtext. I always get SyntaxError: import not found: EchoRequest or SyntaxError: The requested module '/src/components/grpc/echo_pb.js' does not provide an export named 'EchoRequest'. I tried on Firefox and Chrome.

I am not really sure if it is Vite specific or not. It is hard to isolate the error since I have already a Vite+Typescript+Vue+npm application, and the example on the repo has Typescript+Webpack+JQuery have does not use Vite or Vue. Would be possible for us to have an extended Echo example in a Typescript Vue component without Webpack?

A quick way to generate a project like that with Vite is:

sudo npm install -g @vue/cli
npm install -D typescript @vue/cli-plugin-typescript
npm create vue@3
# answer questions
npm install

barrelful avatar Feb 13 '23 21:02 barrelful

thanks for trying all the above mentioned options..

I am not really sure if it is Vite specific or not. It is hard to isolate the error since I have already a Vite+Typescript+Vue+npm application, and the example on the repo has Typescript+Webpack+JQuery have does not use Vite or Vue. Would be possible for us to have an extended Echo example in a Typescript Vue component without Webpack?

Sorry i'm not an expert on JS Bundling to know whether we can do without Webpack. But as far as i understand, some bundler needs to be used so that the dependencies can correctly resolve.

Note that echo_pb.js is generated not by grpc-web but by protobuf-javascript so we cannot easily modify the output.

My understanding is that Webpack will ensure that the dependencies are resolved correctly and generate a single JS file for the whole app.

Are you not using any JS Bundler at all? (e.g. wouldn't code size be an issue for you?) I'm guessing you proved that the code does not work without one.

It would be good if you can try some JS bundler and let us know if the compilation succeeds or if the issue remains afterward.

thanks :)

sampajano avatar Feb 15 '23 23:02 sampajano

Are there any updates on this issue?

sbussard avatar Jun 15 '23 00:06 sbussard

I have same issue right now, now I think using vite + react ts was a bad idea for playing around with grpc in browser. However, problem indeed in type_pb.js file, not grpc-web generated. Hope I will find solution and come back to you with work around.

Shegl avatar Jul 17 '23 12:07 Shegl

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

Aymeric-Henry avatar Jul 17 '23 14:07 Aymeric-Henry

@Aymeric-Henry thx, I used https://github.com/vitejs/vite/discussions/8926 < 1st solution and it's worked for me

Shegl avatar Jul 17 '23 20:07 Shegl

@Shegl Can you please provide a MWE or a link a project, where that solution works. Thx.

boldt avatar Jul 27 '23 14:07 boldt

@boldt hey, in the end it was not working as expected, I use protobuf-ts when I use Vite. https://github.com/Shegl/web-grpc-video-chat you can check how-to

Shegl avatar Jul 28 '23 11:07 Shegl

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!

mvonwaldner avatar Sep 22 '23 10:09 mvonwaldner

@mvonwaldner Thanks so much for sharing your solution! Very much appreciated!!


To others who had issues earlier:

Does the above solution work for you? If this works for some, i'll document this 😃

Thanks!

sampajano avatar Sep 25 '23 22:09 sampajano

No it does not work I get this error

Uncaught ReferenceError: goog is not defined

On the js file there is this import

goog.exportSymbol('proto.command_executor.PostCommandReq', null, global);
goog.exportSymbol('proto.command_executor.PostCommandRes', null, global);

I have used commonjs

on yarn packages I have gprc-web and google-protobuf Part of the code

import { CommandExecutorServiceClient } from './proto/gen//tt/Command_executor_serviceServiceClientPb';

const service = require('./proto/gen/tt/command_executor_service_pb');

function App() {
  const client = new CommandExecutorServiceClient('http://localhost:8100');
  const req = new service.PostCommandReq()
  req.setCommand("ls")
  req.setArgumentsList(["-lah"])
  req.setTimeout(10000)
  const response = client.exec(req,null);

  response.then((res)=>{
    console.log(res);
    
  }).then((err)=>{
    console.log(err);
    
  })

adlion avatar Oct 11 '23 19:10 adlion

@adlion Thanks for your report!

Could you check if you're following the rough steps laid out in our demo app here: https://github.com/grpc/grpc-web/blob/master/net/grpc/gateway/examples/echo/ts-example/README.md

Note that one of the required steps there is webpack (or maybe some other similar code bundler would work), but if you don't do that, then i believe the goog is not defined error is expected.

sampajano avatar Oct 11 '23 21:10 sampajano

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.

adlion avatar Oct 12 '23 18:10 adlion

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

boldt avatar Nov 16 '23 14:11 boldt

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

a2not avatar Nov 17 '23 08:11 a2not