grpc-web: Failed to compile. 'proto' is not defined (also 'COMPILED')

I’m using create-react-app with typescript and grpc-web, grpc & proto generated with command:

$(protoc) -I $(proto_dir) $(proto_dir)/ride.proto --js_out=import_style=commonjs:./rider/typescript/src/proto --grpc-web_out=import_style=commonjs+dts,mode=grpcwebtext:./rider/typescript/src/proto

App is not able to start, it throws tons of errors of form

Failed to compile.

./src/proto/ride_pb.js
  Line 37:     'proto' is not defined     no-undef
  Line 40:    'proto' is not defined     no-undef
  Line 41:    'COMPILED' is not defined  no-undef
  Line 42:     'proto' is not defined     no-undef
 ...

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 31
  • Comments: 20

Most upvoted comments

Maybe a better workaround is to ignore _pb.js files for eslint, which doesn’t require modifying the generated files every time (that gets old really fast).

Create a file called .env in your project root containing only EXTEND_ESLINT=true, then modify package.json to add ignorePatterns:

"eslintConfig": {
    "extends": "react-app",
    "ignorePatterns": ["**/*_pb.js"]
  }

Note that this is currently flagged experimental in the docs. Sources: https://create-react-app.dev/docs/setting-up-your-editor/ https://create-react-app.dev/docs/adding-custom-environment-variables/

Was able to bypass this problem by adding /* eslint-disable */ to the top of generated ./src/proto/ride_pb.js. However it resulted in another error:

Failed to compile.

<path>/rider/typescript/src/proto/ride_grpc_web_pb.js
Type error: Cannot compile namespaces when the '--isolatedModules' flag is provided.  TS1208

    10 |
    11 |
  > 12 | const grpc = {};
       | ^
    13 | grpc.web = require('grpc-web');
    14 |
    15 | const proto = {};

Btw, I get the same compile errors and I am not using Typescript.

If I simply edit the generated files by adding the /* eslint-disable */ at the top just like @argoyb . Be nice if there was some code gen flag to emit this.

Unfortunately the _pb.js files are generated by the --js_out part of the protoc command, which is not owned by us here in grpc-web. We can only control the _grpc_web_pb.js output generated by the --grpc-web_out part of the protoc command.

And I was able to bypass Cannot compile problem by adding // @ts-ignore to line 11 (above const grpc = {};)

From reading earlier in this thread, I have found the full workaround to be the following:

  1. Use TypeScript 2.7+ (it’s in beta now, but it’s needed for this to work)
  2. Add /*eslint-disabled */ and //@ts-nocheck to the top of each of the generated .js files

For the second step, it’s easier to do this in a script. You can use something similar to what was suggested here. For example:

for f in "${out}"/*.js; do
    printf '/* eslint-disable */\n//@ts-nocheck\n' | cat - "${f}" > temp && mv temp "${f}"
done

Hopefully a proper solution arises in the future

I was able to bypass the error by inserting a “fake” object at the top of the foo_pb.js file as such:

var proto = {
  foo: {
    ... nest the rest of the namespaces as appropriate ...
  }
}
var COMPILED;

NOTE: this only works for files generated for protos with no imports. If imports are present, the namespace resolution fails.

It seems clear to me that the Closure-style structure of a proto.foo.bar.v1.MyProto = ... isn’t naively readable as either valid JS or TS because every part of proto.foo.bar.v1 is undefined. Same goes with the COMPILED symbol.

Is there some form of preamble that should be included as well? I.e. is there something being overlooked that provides the missing symbols?

This all works for me when compiled because it can resolve symbols before actually being dealt with “as javascript”'… but the codegen herein is advertised as “just working” without an intelligent compilation step. As generated, the proto module currently isn’t valid javascript and will fail with a proto is not defined error as we’re all seeing because the proto symbol hasn’t been defined.