As progressive web apps become more popular, navigation has become fraught with peril. It's common for apps to make tens of requests to render a single page. Parts of the application load one by one until the entire page is finished. Poor network connections and slow endpoints expose intermediate states to users. Asynchronously loaded page elements shift click targets, resulting in a usability nightmare.
Let's take a look at the how an example application, the Heroku dashboard, suffers from these issues. Here's how the applications list loads.
There are four phases before the page is finished loading. I find the gray layout unnecessary. Just continue to show me the loader, as I can't interact with the page. Without the loader, I'm not sure if the page is still loading.
Besides the fake grey list, the application list page works. I can interact with the page before application metrics load. Once the metrics do load, nothing on the page shifts around or changes place.
The application overview isn't as lucky.
The first problem is the application metrics pane. Like the application list view, metrics are fetched asynchronously. However, here the placeholder is the wrong size. When the metrics load, the pane grows by a small amount. While the change is minimal, it's big enough to disrupt click targets.
The second, larger problem is the add-ons pane. A Heroku application can have unlimited add-ons, making it difficult to size a placeholder element. When the add-ons do load, the dyno pane is pushed further down the page.
The inspiration for this post came from the frustration of having this happen to me. I went to select the worker dyno, but right before I clicked, the add-ons finished loading, causing me to select the web dyno instead.
There a few solutions to this problem.
First, ask yourself if you really need a dynamically-loaded page in the first place. Static pages still work surprisingly well, not matter what Google and Facebook say.
If you do decide to load parts of your page dynamically, make sure your placeholders are correctly sized, both vertically and horizontally. The container shouldn't grow or shrink after the load.
When building and testing your application, throttle your connection to simulate a slow network. This feature is built in to most modern browsers.
Don't cause users to second guess your app. Make navigation consistent under all scenarios.