Kotlin / kotlinx-rpc

Add asynchronous RPC services to your multiplatform applications.
https://kotlin.github.io/kotlinx-rpc/
Apache License 2.0
702 stars 16 forks source link

After js production webpack, code throws TypeError #178

Closed EricDeng1001 closed 1 month ago

EricDeng1001 commented 1 month ago

I developed an website using this project. In development mode everything is fine. After compile to production, landing page shows

TypeError: Cannot read properties of undefined (reading '$metadata$')

After a long time of debugging, I figure out it is withService which throw this error. My snippet of code:

log.info { "initing non auth" }
val y = getHost()
log.info { "got host" }
val rpc = client.rpc { url("ws://${y}/api/auth") }
log.info { "got rpc" }
authService = rpc.withService<AuthService>()
log.info { "got service" }

And log in browser is: image

I initially thought it is websocket's connection problem, but it seems like everything is fine. image

I have check all my dependencies, looked at all samples in this project, and still have no idea what's wrong.

Mr3zee commented 1 month ago

Hi! Thank you for the report, that is indeed concerning, I'll take a look

EricDeng1001 commented 1 month ago

image I think it is this code which throw the error

EricDeng1001 commented 1 month ago

Maybe after complied with production mode, js name is mangled so $metadata$ can not reference to what it should be?

EricDeng1001 commented 1 month ago

Another guess is, in production mode, plugin-generated code is not send to bundle and being mangled together?

marcdownie commented 1 month ago

You'll find a minimal reproducer in nothing other than samples/ktor-web-app.

Although it no longer even builds for me, it can be pressed into service.

./gradlew frontend:jsRun, from the README, now yields:

> Task :frontend:jsBrowserDevelopmentRun FAILED
[webpack-cli] Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
 - options.proxy should be an array:
   [object { … } | function, ...]
   -> Allows to proxy requests, can be useful when you have a separate API backend development server and you want to send API requests on the same domain.
   -> Read more at https://webpack.js.org/configuration/dev-server/#devserverproxy

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':frontend:jsBrowserDevelopmentRun'.
> [webpack-cli] Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
   - options.proxy should be an array:
     [object { … } | function, ...]
     -> Allows to proxy requests, can be useful when you have a separate API backend development server and you want to send API requests on the same domain.
     -> Read more at https://webpack.js.org/configuration/dev-server/#devserverproxy

But if I hack the index.html into the resources/static folder of the server (which I think is the only file that the dev proxy is actually proxying at that point),

cp frontend/src/jsMain/resources/index.html server/src/main/resources/static/

and ./gradlew server:runApp (which does a production js build and copies over frontend.js).

Then, in the browser at http://127.0.0.1:8080/, this issues' exception:

react-dom.production.min.js:188 TypeError: Cannot read properties of undefined (reading '$metadata$')
    at dynamic.kt:48:310
    at WithRPCStubObject.js.kt:27:35
    at t.$_$.y1 (withService.kt:56:20)
    at l (withService.kt:24:12)
    at t.$_$.b (Standard.kt:83:5)
    at ft (ChildrenBuilder.kt:79:9)
    at FC.kt:16:31
    at Standard.kt:83:5
    at FC.kt:16:9
    at du (react-dom.production.min.js:160:137)
ho @ react-dom.production.min.js:188

(As you can tell from #147 I really want the sample code to build and run, mostly so I can use it as a nice minimal template to make you another reproducer!)