cloudflare / workerd

The JavaScript / Wasm runtime that powers Cloudflare Workers

Home Page:https://blog.cloudflare.com/workerd-open-source-workers-runtime/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

πŸ› Bug Report β€” Vite support: "Message is too large" in WebSocket

frandiox opened this issue Β· comments

Hi πŸ‘‹
I'm trying to run Vite in workerd with a similar setup to this. It basically sends code to run in workerd (with dev-only AsyncFunction constructor) via WebSockets.

With a non-trivial app, I'm seeing the following error:

workerd/jsg/util.c++:281: error: e = kj/compat/http.c++:5681: failed: WebSocket protocol error; protocolError.statusCode = 1009; protocolError.description = Message is too large: 5445094 > 1048576
stack: 1019081e0 101908427 102b3833f 10118a324 10192437c 10136b05f; sentryErrorContext = jsgInternalError

Which seems to come from here in capnproto. It looks like WebSocket messages are quite limited, which might be OK for real apps but it's too small for running Vite.

Is there anyway to get around this? There was a similar fix for devtools websockets but it seems it doesn't affect in-app websockets. -- Maybe websocket.receive() could be more generous if unsafeEvalBinding is enabled?

Thanks!

Turns out the message was so big due to inlined sourcemaps. If this is a setting hard to change, we might be able to use fetch instead of WS for this kind of messages πŸ‘

The problem with increasing this limit for Worker apps is there's currently no way to stream a large message gradually. You can only receive a single whole ArrayBuffer or string representing the message in contiguous memory. Since Workers typically have a memory limit of 128MB, multi-megabyte buffers are problematic.

Arguably this line of reasoning doesn't really apply to workerd, especially for dev-oriented use cases, but we're hesitant to make workerd behave differently since it may confuse people when they go to deploy their app later.

The ideal fix to this is to add an alternative way to receive messages where large messages can be delivered as ReadableStreams. But, there's some engineering work needed to build that.

Do you control this protocol? Is it at all possible to split large messages into multiple pieces?

I see, thanks for checking this!

Do you control this protocol? Is it at all possible to split large messages into multiple pieces?

It looks like we have enough flexibility in the latest Vite beta to do different things for different types of messages:

  • Keep using WS for HMR events, which have a smaller payload.
  • Use unidirectional fetch to retrieve code and sourcemaps.

Therefore, we can keep the current limit for WS since HMR events should be <1MB πŸ‘
Thanks!