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

ES Modules Support?

Open alangdm opened this issue 5 years ago • 22 comments

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

alangdm avatar Apr 12 '19 07:04 alangdm

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 avatar Apr 15 '19 14:04 jonahbron

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

alangdm avatar Apr 23 '19 08:04 alangdm

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

alangdm avatar Apr 23 '19 08:04 alangdm

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.

RXminuS avatar May 24 '19 07:05 RXminuS

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

zeidoo avatar Feb 21 '20 07:02 zeidoo

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:

image

  • 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 be esm-compatible.

Example:

Generated import paths Modified to be esm-compatible CDN alternative
image image image
  • 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 NOT esm-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 be esm-compatible in a PR here --> https://github.com/Arxcis/grpc-web/pull/1

  • I would love to discuss this more :rocket:

Arxcis avatar Oct 16 '20 13:10 Arxcis

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 😅

Arxcis avatar Oct 20 '20 23:10 Arxcis

Any progress on this issue?

chris-kruining avatar Feb 11 '21 16:02 chris-kruining

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:

Arxcis avatar Feb 11 '21 17:02 Arxcis

I am also waiting patiently. 😢

frederikhors avatar Mar 12 '21 17:03 frederikhors

Are there any plans for this to be worked on? Currently having issues with using Vite alongside grpc-web.

andershoegh avatar Feb 28 '22 07:02 andershoegh

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

sxwebdev avatar Mar 18 '22 16:03 sxwebdev

Please 🙏

loeffel-io avatar May 09 '22 08:05 loeffel-io

is grpc supported es6?

Masterxiechengxun avatar May 11 '23 06:05 Masterxiechengxun

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.

PrestonMonteWest avatar Dec 22 '23 22:12 PrestonMonteWest

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"

Threebow avatar Feb 09 '24 08:02 Threebow