-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
feat: native support for Websockets #12973
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…ionality for different handlers at different URLs, added example use cases to options-2 test app, added upgrade function for supporting additional adapters, and much more.
🦋 Changeset detectedLatest commit: d8d803f The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
preview: https://svelte-dev-git-preview-kit-12973-svelte.vercel.app/ this is an automated message |
@LukeHagar LMK, if you need any help with this (you can reach me also on discord |
Small input to the Durable Object thematic. No there shouldn't be any magic needed. a simple browser WebSocket can connect to it even with hibernation. BUT, due to websockets not supporting reconnecting out of the box, |
Hey everyone, little update here. A group of maintainers are having a team offsite ahead of Svelte Summit later this week, and we devoted much of today's session to talking about websockets. It was a great conversation and we had some realisations that would have been much harder to reach without the in-person aspect. We concluded that this PR makes some great headway BUT from an authoring perspective there's a bit of an impedance mismatch between the
We have some ideas we really like on what |
I appreciate the thought being put in here, and I can agree with all of the points on the interface and usage experience. And I'm very happy the conversation is ongoing :D Thanks for the update! |
Cool this is being worked on. Enjoy the summit.
I am just thinking about a notification counter that sits in the page header on all pages.
with or without requiring |
This really depends on your backend and usecase. Durable Objects are near perfect for scaling many kinds of collaborative apps. E.g. game servers, or an educational apps designed to serve a classroom where all the pupils are in the same location. The DO servers will end up getting automatically located at the edge near the users. There is no real penalty in terms of pricing for having one Durable Object per game or classroom instance. One of the problems I see for crossws is that while it did allow for a Durable Object backed DO. I think it is hard to make this work for different classes of DO in the same app E.g. the game server and the lobby server (each requires their own DO). The web socket adapter would need to be set up in https://crossws.h3.dev/adapters/cloudflare#durable-objects So for me there are two problems how to hear a |
Thanks for the feedback @Rich-Harris (just found about updates from a chat with @benmccann) Understandably, you might prefer to implement WebSockets standalone and design differently. I would love to have a chat to discuss more with svelekit team. There are a lot of compatibility details part from end user API that could be reused. Only to answer some of your concerns:
Peers only get notified about the topics they subscribe, but this is true; they are not isolated (between different resolved hook-sets). I had been talking with other folks before, and we might change that.
The global publish method is available on the main instance. Peers can auto-join topics mapped from their routes to have an API like
CrossWS also exposes an abstraction over SSE to give the same API: https://crossws.h3.dev/adapters/sse -- @philholden Re CF DO, we recently added new resolver option that gives full flexibility on routing upgrade request, to Durable instance. h3js/crossws#130 |
Hell to the yes about a << POST+SSE mechanism >> |
Thanks @pi0 the routing looks helpful. |
Sorry to reopen the thread again. I was very excited about WebSockets, and even if it’s not as perfect as intended, there should at least be a branch for testing and using crossws in the meantime, while the perfect solution is being worked on. |
We'll be sharing some thoughts very soon on how we plan to evolve data loading in SvelteKit, and real-time is part of that, but we're mainly thinking about unidirectional stuff (i.e. SSEs). Curious if people have use cases for WebSockets specifically, rather than real-time more broadly? |
Personally, I use SvelteKit quite a bit with real-time games, where data needs to be sent between the client and server bidirectionally at a fairly constant rate. To my knowledge, using a technique like SSE would require every client to server interaction to create a separate request, adding a lot of overhead for updating variables that need to change quickly, like position. I'm currently using this PR to develop another game, and I've found it to be a very smooth experience when compared to external methods that I've used in the past, which add many complications in server setup and deployment. (This comment isn't really about the PR, just answering the use-cases question above) |
I will use this PR as well. I haven’t had any issues with it so far — I almost finished a game engine using it. I thought it was heading in a good direction. To answer the question: I use bidirectional communication 99.9% of the time, much more than SSE — not just for games, but also for other projects I’m starting to develop for the company I work for where we need websockets. This was something no other framework offered, and it was truly revolutionary. |
We are using Sveltekit + websockets in two different projects. One is a semi-real time gaming system. The other project is an MVP that needs to handle continuous interaction with thousands of remote systems (which themselves are in production). We are not using this PR build directly, but I used it as an inspiration to write a custom vite plugin which works mostly fine. The former project (gaming system) was earlier using SSE (since I hadn't figured out sveltekit+websocket back then). But SSE was a pain to work with. The connection sometimes doesn't close cleanly on the server, eating server resources. And because it's unidirectional, you need to have a separate route for client initiated communication. I don't really see the point of going back to SSE, when a much more capable alternative exists. |
I would definitely agree that a perfect solution here would allow for native support for SSE, WebSockets, and WebTransport, and the ability to use them independently. I am greatly excited to hear more about the Svelte team's plans for the direction here, and excited for a sveltey WebSocket experience |
I actually agree with @Rich-Harris — a lot of developers aren’t even aware that things like Server-Sent Events exist. Most just default to WebSockets and assume that’s the only option for real-time communication. Since SvelteKit is positioning itself as the go-to framework, it really makes sense for it to support all the common real-time patterns — not just WebSockets, but also SSE and others. |
Here's the RFC for Remote Functions we just published, which hopefully gives you an idea of the broader context. Essentially, we want to separate data fetching from routing. Not shown in the RFC is this idea for streaming real-time data from the server —
This would be powered by Server Sent Events, and would thus be available on every platform that supports streaming responses. It's a good approach because it works the same way everywhere and works very naturally with serverless platforms. It also has limitations — there's per-request overhead, and it's one-way only. So my question in #12973 (comment) was trying to gauge how many use cases would be satisfied by this design, vs something that is specifically backed by Hope this provides some clarity — I realise that many of you are chomping at the bit for this stuff to be built in! |
Awesome. This sound like something that is trending in the direction I enjoy.
This seems relevant: I work on apps that push data pretty fast, so keeping a websocket open makes sense. I really like doing bidirectional communication over persistent websockets, because opening new connections for every request seems like not the best thing, when you are receiving lots of data regularly anyways. |
I believe the statement regarding server sent events and platform compatibility is referring to there being hosting platforms that do not support web sockets server side, Vercel being a good example. |
I am not sure, but I think it boils down to long running processes are not typical of most hosting options that uses runtime like workerd. If you want them, you need to host it yourself using Bun, Node, Deno, etc. So far, I have not been able to get SSE or WebSockets to work at all with these platforms like Vercel or Cloudflare, but have running my apps via the Bun runtime in an OCI container like Docker with zero issues. Going serverless means restricting what runtime features are present. To leverage long-running process type hosting (not serverless), I typically use Svetle's node adapter even though I am using bun, then pass the --bun flag during runtime like this |
The functionality is available in Cloudflare Workers (link). I personally had no issues when I tried it out, but I did not try it with a complex application. |
I'm building a multiplayer music studio. I use WS for signalling for WebRTC and keeping a general tab on users in rooms etc. I use Socket.io mainly because it provides a bunch of niceties such as room management etc that is actually quite fiddly to get right just using vanillla JS. | I also use it to keep track in memory of the current "music game state" which is then periodically saved to Mongo based on updates from users and provided to users when they join. I also use websockets to determine the current "time" - ie User pings GET_TIME and then adds half of the round trip. Not sure if there's anything there that goes beyond typically "live multiplayer game", but that's above my pay grade ;-) Currently this is all node as a separate node server which adds a bit of faff and deployment fiddling, though the separation of concerns is a positive. |
As someone who has been using SSE with Sveltekit for a couple years now, this sounds great. I have yet to face a problem that required me to use WebSocket. I have a question will every Since if each stream uses it's own endpoint and connection, having multiple real time streams is inefficient, especially on servers. |
Yes, the plan is to re-use the same connection for multiple |
Websockets allow binary data SSE does not. Automerge uses binary data to sync efficent conflict free replication data structures (Google docs style multi user experiences). Svelte's reactive nature makes it a good fit for these kinds of realtime multi user apps. |
This is looking great! Please make sure there's a way to catch client disconnects on the server. In ORTC we are given an AbortSignal that we can use to cancel/cleanup the server side resources if the SSE connection is dropped. export const time = query.stream(async function* ({signal}) {
signal.addEventListener("abort", () => { /* ...cleanup... */ })
//...
}); This also very useful for all the other libraries that use the same pattern, you can just pass this along instead of making your own AbortController. |
This looks really nice! Is there a method to get URL slugs from a peer connection? Right now the only way to get the slug is during the upgrade connection and by manually parsing the peer.request.url string (as far as I know). |
This PR is a replacement to #12961 with a completely different Websocket implementation using
crossws
that should be fully compatible with all major runtimes.Functionality has been validated locally using basic tests in the
options-2
test app.Here is the new usage experience.
+server.js
The newest implementation allows different sets of handlers to be implemented on a per-route basis. I have tested some basic uses of websockets locally to much success.
This PR is intended to:
Resolve #12358
Resolve #1491
Steps left
+server
exports validationPlease don't delete this checklist! Before submitting the PR, please make sure you do the following:
Tests
pnpm test
and lint the project withpnpm lint
andpnpm check
Changesets
pnpm changeset
and following the prompts. Changesets that add features should beminor
and those that fix bugs should bepatch
. Please prefix changeset messages withfeat:
,fix:
, orchore:
.Edits