- A user should be able to interact with UI when they see it, so reduce time between UI rendering and interactivity.
Gone are days of building multiple desktop apps for each and every platform. Browsers have provided uniform platforms, and great core elements for building applications, games, and virtual reality experiences — in addition to the original purpose of browsing the internet.
2. Web apps vs. websites
I would like to take a minute and highlight that web apps and websites are two different things at their core.
Websites are content first and have a primary experience of sharing information, which would mostly be static by nature.
Web apps, on the other hand, provide interactive functionality first, which empowers users to achieve their task, e.g. CRMs, IMs, and webmail.
The alternative is to look at how information flows.
On one side, the user requests and consumes content, and they are in control of what they are viewing and at what pace.
On the other, the system is in control, and it needs to notify the user about new content as soon as possible.
With that in mind, we can conclude that it is in the best interest of websites to optimise content delivery so that a user can view it as soon as possible; the ideal time being less than a second from the user requesting content.
Web apps need to provide smooth experiences throughout their use, and users can usually tolerate slower loading times, as once loaded, most of the functionality would be available.
Not everything is black and white however, and there are sites that need to interact like apps (e.g. wikis, forums), or apps that need to appear like websites (e.g. online retail).
The key point is to achieve the balance between being fast and providing core functionality, with some concessions in between.
3. With great power comes great responsibility
As more people are accessing the internet on mobile devices, this must be considered, as they have limited resources and power, and developers and website owners are responsible for what we serve users and how we utilise the resources a device provides.
It horrifies me when I see a website proliferated with ads, consuming 1GB of memory, which eventually crashes the browser tab.
3.1. Startup performance
There are a number of techniques browsers employ to speed it up, but, at the end of the day, parse and compile stage is crucial.
The issue is that each part is requested, loaded, and executed on demand, and that part might require another, which creates a sequence of request->parse/compile->execute iteration.
The ideal reality would be to use code-splitting and route-based chunking to produce one shared bundle that is required by all/most parts of the website, and one bundle per route/part of the website that covers functionality of that part only.
There is new Cache API available for caching request/response objects, which can be eagerly populated.
Progressive web apps use this API to provide offline experiences and to improve reliability under uncertain network conditions. This API can be used to improve asset fetching by precaching resources.
3.2 Third-party scripts and iframes
Including third-party scripts can be highly detrimental to overall performance.
Almost all websites have a number of third-party scripts, ranging from analytics and metrics scripts, to advertisement/retargeting scripts and social integrations.
Furthermore, iframes run in the same process as the main page, so that means that iframes can block your main thread and delay the startup time or lead to sluggish event handlers; degrading user experience.
Websites with tremendous amount of Facebook like buttons, embedded YouTube players, and other social widgets, visibly suffer from this.
3.3. Popular frameworks
Almost every website or web app uses one or more frameworks. These frameworks add to the total script size. Here is a list of some popular frameworks and their sizes, with some of them having dramatically trimmed their weight over the years:
|Angular 5||ng cli 1.6.7||44K|
|React + ReactDOM||16.4.0||94K + 7.1K|
|Preact (+compat)||8.2.9 (3.18.0)||8.1K (9.3K)|
Now, you might ask yourself, do I need to bring Ember for a static website? What about React? Why can’t my simple website be composed using Preact? I have experience with jQuery, could it be sufficient?
Some of these frameworks are geared towards Single Page Applications and some are more general utility libraries.
When picking a framework, you need to keep in mind which problems it is better at solving, and how to utilise it to bring out its best qualities.
For SPAs, frameworks that manage whole DOMs are key. Using a framework like that, in the same manner, for building a regular website, is misusing its power.
Don’t use React/Angular/Vue to build websites, even if you can. That’s not what they are good at.
I am not suggesting that they are not a good fit, for as component centric frameworks, they actually fit very well for making interactive components that are added separately to the page to enhance experiences, for when:
- You have an online retail website, and you need a mini-basket on every page, make a static fallback that is overloaded and enhanced with a component once it is available.
- You need search box with suggestions (make a simple one, and enhance it with a component).
- You need a main hamburger menu on mobile, make CSS/HMTL only fallback first, and then enhance with a component (you will see why later).
Remember KISS? I suppose it has been out of fashion recently. When you choose tools for a job, ask yourself if it be simplified and still let us be productive? Does it deliver quality?
There are concessions to be made, but you must not assume that everyone has access to top end phones, or the best mobile networks.
It is costly and hard to run prerendering on a big scale. Check out this article, where Browserless discusses its experience in running 2 million headless sessions, and here, Ahrefs mentions that it believes that its customers are not ready to pay for prerendering on all websites.
- Depending on network connectivity, users might have to wait longer than just initial page load to see any content, which the search engines take into account.
- Making sure it works in Chrome 41 would require polyfilling any features that it does not support. Does this not remind you of supporting Internet Explorer? Now, imagine supporting Bing’s version if/when they make it. What about Yandex? Baidu? NameTheEngine?
To summarise, from an SEO perspective, if you encounter a fully or partially client-side rendered website and certain content is not indexed or crawled and you want to improve it:
- Is the client interested in other search engines apart from Google? If the answer is yes, there is only one solution, the website MUST prerender.
- Ask whether they can prerender HTML for everyone? If the answer is no, tell them that they MUST prerender at least for search engines.
- If the answer is still no, compromise on partial prerendering, but highlight the risks, that non rendered content might not be indexed.
Ultimately, what matters is that a user can interact with the page. There is a metric known as Time to Interactive, which Google defines as:
Time to Interactive is defined as the point at which layout has stabilized, key webfonts are visible, and the main thread is available enough to handle user input.
Here is quick TTI primer.
On mobiles, with unpredictable network connection and highly variable performance, providing fast above the fold interactivity is crucial.
Hambuger menus are the first UX elements that are susceptible to a “dead UI” effect, which appears when UI and page is loaded from user’s impression, but it is actually still loading and initialising.
Any attempt to interact with the UI element fails, and leads the user to believe that it is broken, which makes the site seem broken and results in the user abandoning their task.
The following table shows first paint, meaningful paint, and time when hamburger navigation becomes interactive (when event listener is attached). They were collected on desktop Chrome with mobile device emulation enabled, without throttling network or CPU.
|Website||Total JS (approx) size||Bundled||Time to first paint / meaningful paint||Hamburger TTI (cached)|
|Jaguar (Shop)||5.72MB||Yes||~500ms / ~830ms||~2953ms (~2577ms)|
|Richer Sounds||4.77MB||No||~982ms / ~1574ms||~8237ms (~5239ms)|
As we can see, the experience of navigation on mobile is delayed by substantial amount of time.
Balancing pros & cons, productivity, and experience is a good way to start when picking a framework.
But picking a framework when it’s not geared towards something, is a good way to shoot yourself in the foot later.
Priority should be enhancing user experience rather then denying it due to obsolete browsers/devices. Serving as much as possible in HTML helps us achieve it.