In any application, data needs to be collected and displayed to the user for further action. This pattern is so common, there is a name for it: the MVC pattern, or Model, View, and Controller — the model is built and passed to the view by the controller. The order in which the model and view are executed can have a significant impact on real and perceived performance. Further, where the execution happens can also have a significant impact on system-level performance; the further upstream it happens, the more likely that it can be shared downstream, and thus the more likely overall performance is improved.
But not all data cost the same; some take longer to resolve than others. To improve perceived performance, fast data can be server rendered in the initial payload, and slow data can be browser rendered (or server rendered with Hotwire ) later. The browser can then download and start using associated assets whilst waiting on the slow data. This way, a portion of the page is visible and usable much earlier. This technique is similarly used when inlining critical CSS and delaying the rest of the CSS until later.
Where multiple slow data responses are awaited on, each requires its own XHR request. Alternatively, multiple responses can be multiplexed into a single Server Sent Events or Websockets connection.
As if a traditional SPA wasn't complex enough, there's server rendered complexity, and even further sync-vs-async data complexity… We are drowning in COMPLEXITY!!!
It turns out that we already have a powerful framework to do all of this parallelism — the browser. Browsers are capable of progressively rendering partial HTML documents as they are streamed from the server (using
Transfer encoding: chunked). With only just the HTML
head, or with a few initial lines of the
body, the browser can preload, prefetch, and preconnect associated assets in parallel. It can even render these partial HTML fragments without corresponding closing tags. Even without CSS, it can download responsive images. Using
Recall the MVC? Most frontend libraries/frameworks provide synchronous view engines. That is, the model needs to be first completely built, and the view thereafter. Now, imagine one that allows each component (and sub-components) to be rendered asynchronously. The model and the view can be interleaved, opening up a whole new class of capabilities:
There are challenges, of course. Any header or content already sent to the client, cannot be unsent. This can result in responses that are not self-consistent, and may need to be solved with appropriate messaging. Further, the push model could mean that unsolicited content could be sent.
There may/will be others.