Chrome offline network emulation and WebSocket

If you have used Bubble, you might have noticed that we rely very heavily on WebSockets. In fact, our entire API is built on WebSocket (well technically not exactly, because we use socket.io and they will fallback to long polling on platforms that do not support WebSocket).

Towards the tail end of our sprint, we started to look more into the non-happy path that our users could face. Ideally, our users will be on a stable connection, and the clients will be able to send and receive messages easily. However most of our users on mobile will be on flaky connections, moving in and out of 3G and WiFi, and going into places without any connectivity. Thus we wanted to ensure that when the connection is lost, our app will be able to come recover quickly and flawlessly.

Any web developer will appreciate the Chrome Dev Tools, to me it is a magical piece of software that provides you super powers to inspect and debug any website (and in it’s recent update it can do more than that). I like to use it for its mobile and responsive view, and in my previous project I got to use the Application panel to debug service workers.

Experienced developers will know that there is an “Offline” checkbox in the network panel and the Application panel, this was useful to help test service workers — I would turn on offline emulation, reload the page, and see if the service worker has intercepted those fetch requests correctly.

To me this seemed like a great way to test my WebSocket disconnection. So I decided to try it. I would connect, make an API call to verify that connection worked, check the Offline box, and try to make an API call again (which will fail), then uncheck the Offline box, and finally try to make an API call which will succeed.

However, offline emulation does not work for WebSocket! I found a chromium bug that tracked this issue:

In short, most network calls in Chrome goes through a Fetch API, which has throttling capabilities (offline is equivalent full throttle!), but WebSockets, (and WebRTC plus some other kinds of requests), does not go through the same Fetch API. Therefore for throttling to work it requires a bit more thought and work.

The only other way I could think of to test disconnect was to actually disconnect! So what I did was to fire up a server on my laptop, look up the local ip on my laptop, and on my phone connect to the server (you can probably use something like ngrok too). By default, socket.io sends a ping heartbeat (which determines if a client is still connected) every 25 seconds, which was too long for me to wait. Instead I configured my server to send heartbeats every second, like so:

var server = new engine.Server({
pingInterval: 1000,
pingTimeout: 1000,
});

This makes the socket server send ping to the client every second, and if the client doesn’t respond within a second it considers it disconnected. This was fast enough for me to test the reconnect scenario.

If you have not tried Bubble, try it out! We are both on the web, and on the Play Store.