grpc-web
grpc-web copied to clipboard
ES Modules Support?
Hi, I'm new to grpc-web and I was checking your Web basics tutorial when I noticed that the client code generator only supports Closure and common.js
Now that ES Modules are supported on all modern browsers, is there a chance that you'll have a generator for them? That would allow the library to be used without any build process which would be great imho
This isn't a direct answer, but the TypeScript output does support modules. If you're not using TS in your project, a workaround would be to re-compile from the TS output of protoc down to ES6.
@jonahbron I tried this, it was a bit annoying to configure but I managed to get it working
Here's a sample bash script for generating the ts files and the tsconfig.json to compile it to esm in case anyone has this same problem
protoc -I ./protos protos/*.proto --js_out=import_style=commonjs:./protos/ts --grpc-web_out=import_style=typescript,mode=grpcwebtext:./protos/ts
{
"compilerOptions": {
"target": "es2015",
"module": "es2015",
"allowJs": true,
"outDir": "../esm",
"rootDir": "./",
"strict": false,
"moduleResolution": "node",
"esModuleInterop": true
}
}
Then again this only worked for the grpc-web_out files, the other files were still generated as commonjs modules, but I guess it's something
This actually seems to be a real problem when trying to use grpc-web with something like create-react-app or any Babel 7 Typescript. Since they don't support commonjs only ESModules. Currently the only solution seems to be to manually rollup the exports using something like this https://github.com/rollup/rollup-plugin-commonjs. Would love to find a more permanent solution though.
ESM modules would be really nice.
In the mean time, if you use grpc web with stencil and rollup, see this comment https://github.com/ionic-team/stencil/issues/1343#issuecomment-589528554
That would allow the library to be used without any build process which would be great imho
By the way, this is only true if both grpc-web
AND the generated client-stubs has esm
-support, so this issue has to be solved in two parts:
Part 1: Generating an esm
-compatible grpc-web-client:
- Part 1 is 99% solved already with the
import_style=typescript
-option :+1: - The only thing that is left for me to do after generating the
EchoServiceClient.ts
above, is to update the import paths to beesm
-compatible.
Example:
Generated import paths | Modified to be esm -compatible |
CDN alternative |
---|---|---|
![]() |
![]() |
![]() |
- FYI: Here is my
protoc-gen-grpc-web
-version:
$ brew info protoc-gen-grpc-web
protoc-gen-grpc-web: stable 1.2.1 (bottled)
Part 2: Convert the grpc-web
-package to be esm
-compatible.
-
After modifying the paths in Part 1, I will still get an error if I try to run my generated client directly in a browser, because the modules imported from
../node-modules/grpc-web/index.js
and https://cdn.jsdelivr.net/npm/[email protected]/index.min.js are NOTesm
-compatible. -
Neither is
'./echo_pb.js'
, and it's depedency../node-modules/google-protobuf/google-protobuf.js
, for that matter, but that is out of scope of this repo. -
This inspired me to explore how the
grpc-web
-package can be converted to beesm
-compatible in a PR here --> https://github.com/Arxcis/grpc-web/pull/1 -
I would love to discuss this more :rocket:
Part 2: Work in progress update
- So I have been hacking along on my fork PR of
grpc-web
here --> https://github.com/Arxcis/grpc-web/pull/2 - I have put together a "transpiler" of sorts, which takes the exports.js-file as an input, and traverses all the dependencies, and outputs a
es_modules
-folder, with transpiled.js
files. - I have gotten to a point where the browser is able to load all the modules - but not run. (see demo here --> https://github.com/Arxcis/grpc-web/pull/2)
- The main issue I am running into now, is that the ~
closure-library
~ the code I have generated has a few circular dependencies of top-level values, which the browser's ES modules loader is not too happy about. (details here --> https://github.com/Arxcis/grpc-web/pull/2) - ~I honestly don't know how to proceed from here~ I think I would have to improve my generator to not generate top-level values, bu try to transform modules into ES classes instead, to solve the circular dependency issues :pray:
- Alternatively We could generate modules wrapped in an immediately invoked function closure, which returns the module.
- Alterntive 2: We could just write code without circular deps. I am not holding my breath 😅
Any progress on this issue?
Any progress on this issue?
FYI: My experiment mentioned above, ended without any success. I have no affiliation with the maintainers of this repo. I don't know what the plan is. I am patiently waiting like you :pray:
I am also waiting patiently. 😢
Are there any plans for this to be worked on? Currently having issues with using Vite alongside grpc-web.
Are there any plans for this to be worked on? Currently having issues with using Vite alongside grpc-web.
You can use this package https://github.com/timostamm/protobuf-ts which works great with Vite
Please 🙏
is grpc supported es6?
Definitely would be nice to have for bundlers that don't support CommonJS. I'll try that rollup solution above, but first-party support would be much preferred.
Not sure if this will work for everyone, but it worked for me. I had this error when trying to import the generated client in an ESM project:
require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and 'X\package.json' contains "type": "module".
To treat it as a CommonJS script, rename it to use the '.cjs' file extension
I fixed it by creating a package.json
in the directory of my generated client (e.g. @/generated
) with the following contents:
{
"type": "commonjs",
"main": "xyz_client_pb.js",
"types": "xyz_client_pb.d.ts",
"dependencies": {
"google-protobuf": "^3.21.2"
}
}
I needed to install google-protobuf
from within the directory for this to work.
This essentially un-sets your "type": "module"
setting for only those generated files. It seems you can pretty much use it as normal, for example:
import { XYZRequest } from "@/generated"
import { XYZClient } from "@/generated/xyz_client_grpc_pb"