Writeup of the DjangoCon Europe 2019 talk »Reduce, Reuse, Recycle - Persisting WebSocket connections with SharedWorkers« by Aaron Bassett
Aaron Bassett: Aaron Bassett has lived in Ireland, Scotland, and is currently wandering around central and eastern Europe. He is a recovering senior software engineer turned award-winning Developer Advocate at Nexmo where he leads their content creation.
What are websockets? In the dark ages we had to use iframes if we wanted to update part of a page – the only previous
alternative was to reload the page. Or you could use
Transfer-Encoding: chunked, which led the browser to accept
content until the server told it to stop, which was used mostly to push script content. Next up (ignoring comet), we had
Ajax requests, which you could use to send out asynchronous requests, and establish polling.
This is a hack. It's brittle, it's hacked on instead of designed in, both on the server side and the client side. It forces you to re-send all the headers (which can include larger cookie headers). This is a problem once you have several thousands of users! Both for your server, but also for users with limited bandwidth. Also, this hack isn't bidirectional, so the server could not just decide to push data.
On the client side, we have
onclose functions, on
new WebSocket(url) objects.
Using Channels, we're talking about Consumers (instead of Views) with an
async def connect(self), which handles all
incoming connections, and a similar
Having a lot of users connect to you via many tabs each is expensive. Shared WebWorkers help with that – they bundle connections coming from the same browser and going to the same origin. They also have onconnect methods, and are also bidirectional – meaning you can communicate from shared worker to page, and back. Basically you're writing your own little bundler/multiplexer/proxy in ~20 lines.
Please note that Shared WebWorkers are browser-local, not host-local. Shared WebWorkers are only available in Firefox and Chrome and Opera, plus Blackberry browser. Safari removed it, and IE/Edge never started. Happily, we don't have to change any server-side code, so support for older browser is not an issue.