URL hashes and deep linking

Hashchange

The Zulip web application has a nice system of hash (#) URLs that can be used to deep-link into the application and allow the browser's "back" functionality to let the user navigate between parts of the UI. Some examples are:

The main module in the frontend that manages this all is static/js/hashchange.js (plus hash_util.js for all the parsing code), which is unfortunately one of our thorniest modules. Part of the reason that it's thorny is that it needs to support a lot of different flows:

When making changes to the hashchange system, it is essential to test all of these flows, since we don't have great automated tests for all of this (would be a good project to add them to the Puppeteer suite) and there's enough complexity that it's easy to accidentally break something.

The main external API lives in static/js/browser_history.js:

Internally you have these functions:

Server-initiated reloads

There are a few circumstances when the Zulip browser window needs to reload itself:

An important detail in server-initiated reloads is that we desynchronize when browsers start attempting them randomly, in order to avoid a thundering herd situation bringing down the server.

Here are some key functions in the reload system:

All reloads

In addition to saving state as described above when reloading the browser, Zulip also does a few bookkeeping things on page reload (like cleaning up its event queue, and saving any text in an open compose box as a draft).