Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

grpc-web not working in a Vite+Typescript app #1242

Closed
loicmagne opened this issue May 11, 2022 · 39 comments
Closed

grpc-web not working in a Vite+Typescript app #1242

loicmagne opened this issue May 11, 2022 · 39 comments

Comments

@loicmagne
Copy link

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 ?

@Krzysztof-Dziardziel
Copy link

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
Copy link

Krzysztof-Dziardziel commented May 31, 2022

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

@lbensaad
Copy link

lbensaad commented Oct 9, 2022

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

@FredrikMeyer
Copy link

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

@wirekang
Copy link

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

@lbensaad
Copy link

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.

@barrelful
Copy link

barrelful commented Jan 16, 2023

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

@staticdev
Copy link

staticdev commented Jan 16, 2023

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

@sampajano
Copy link
Collaborator

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

@barrelful
Copy link

barrelful commented Jan 22, 2023

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

@staticdev
Copy link

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

@sampajano
Copy link
Collaborator

sampajano commented Feb 7, 2023

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

@barrelful
Copy link

barrelful commented Feb 10, 2023

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

@catarse-natural
Copy link

catarse-natural commented Feb 10, 2023

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.

@sampajano
Copy link
Collaborator

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

@barrelful
Copy link

barrelful commented Feb 13, 2023

@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

@sampajano
Copy link
Collaborator

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

@sbussard
Copy link

Are there any updates on this issue?

@Shegl
Copy link

Shegl commented Jul 17, 2023

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.

@Aymeric-Henry
Copy link

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

@Shegl
Copy link

Shegl commented Jul 17, 2023

@Aymeric-Henry thx, I used vitejs/vite#8926 < 1st solution and it's worked for me

@boldt
Copy link

boldt commented Jul 27, 2023

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

@Shegl
Copy link

Shegl commented Jul 28, 2023

@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

@mvonwaldner
Copy link

mvonwaldner commented Sep 22, 2023

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!

@sampajano
Copy link
Collaborator

sampajano commented Sep 25, 2023

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

@adlion
Copy link

adlion commented Oct 11, 2023

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);
    
  })

@sampajano
Copy link
Collaborator

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

@adlion
Copy link

adlion commented Oct 12, 2023

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 vitejs/vite#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.

boldt added a commit to boldt/grpcweb-cra-to-vite that referenced this issue Nov 16, 2023
@boldt
Copy link

boldt commented Nov 16, 2023

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: #1242 (comment)

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: vitejs/vite#8926 (reply in thread)

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

It throws:

Uncaught TypeError: service.EchoRequest is not a constructor

@a2not
Copy link

a2not commented Nov 17, 2023

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

@boldt
Copy link

boldt commented Nov 17, 2023

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,
    } 

@sampajano
Copy link
Collaborator

@boldt Thanks so much for creating a minimal repro case to help the debug. And very happy to hear that you've found the missing puzzle!

Does that mean that, with your approach, we can resolve this issue now? 😃

@sampajano
Copy link
Collaborator

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

@a2not
Copy link

a2not commented Nov 18, 2023

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 #535.

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

@sampajano
Copy link
Collaborator

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 #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
Copy link

a2not commented Nov 18, 2023

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

@sampajano
Copy link
Collaborator

@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
Copy link
Collaborator

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

@kindlychung
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests