Website Performance. Big Basic Checklist 

A fast website is something very obvious and simple: the site loads quickly and does not freeze. “If you make people wait 3 seconds, you start losing users” is a rule that probably every web developer has heard. But this rule is only the tip of the iceberg, both when it comes to the reasons customers are lost and when it comes to real outcomes.

This article is a comprehensive collection of information about performance: from the history of the first analysis tools and the reasons they appeared, to modern problems and universal ways to improve a website.

Performance factors 

First, what does a fast website mean? Site speed is a combination of factors. Some of them are easy to measure, including in a “lab” environment, while others work only at the level of the user’s perception.

And perhaps the three‑second rule today can no longer be called the main and only correct one. Most users now have fast enough internet to load even a very heavy page in a couple of seconds. Further optimizations of load speed are done mostly for the remaining 20% of customers. But there are factors that affect 100% of customers.

These are factors of how the site is perceived and how it feels to interact with it. And if you try to identify the main principle of a fast website today, it is this: “the user should not feel the site working.” To achieve that, you need to consider not only site speed metrics, but also the user experience.

User experience 

You have probably run into situations where you search for an answer, open a site, start reading, and ads keep loading nonstop on the sides. Or you open a landing page for a tool to see how it is used, and it stutters because of animations. Or you click a button and nothing happens.

These are very common cases that almost every third site is guilty of. But there are less obvious cases too.

Site feedback 

Imagine two blogs. In both, you go to the second page of an article list. In the first case, nothing happens. One second, two seconds, you click again. Another second, and here is the long‑awaited navigation to the new page. Next time you do this, you will very likely click again after just a second. After that, repeated clicks will happen immediately. The reason is simple: the interface gives no feedback that the action was successful. A kind of “CTRL+C effect.”

In the second blog, right after the navigation it shows skeleton placeholders for the articles. That same one or two seconds of waiting feels different. The user understands that loading is in progress and the articles are about to appear.

But what happens with the same scenario on a 5G connection?

The first site will load and show new articles after about 200 ms of a blank screen. The second site will immediately show a skeleton, and after 200 ms it will replace the skeletons with the actual articles. During those 200 ms the interface changes several times, with jumps and flicker. So an overly fast response significantly worsened the user experience. This happens with all metrics: improving one can lead to worsening another. Every optimization is analysis, checks, tests, and searching for the best solution for a specific case.

In this case, the optimal solution is to show a loader or skeletons with a small delay, usually around 150 to 300 ms. After a second, you can show an additional message like “This page is taking longer than usual, please wait.” This kind of solution is used, for example, in Jira and Notion. Usually users do not notice these tricks (and that is exactly the key factor of a fast site, as mentioned before).

Another possible solution is a progress bar. In this case a line appears right away showing the loading percentage. The percentage can be symbolic, moving in steps (started the action: 10%, sent the request: 20%, received a response: 90%). You can see this approach, for example, in GitHub.

Showing content 

The other side of the same situation is that the user should see something as early as possible. This applies both to the initial page load and to everything that happens after.

For example, if a page has a popup with cards for related tasks, you should not wait until all tasks are loaded and only then open the popup. The user may not even need that list. It is much better to show the popup right away with the data you already have and indicate that the tasks are still loading (using the approaches mentioned above).

Some services show a full-screen loader during the basic page load. LinkedIn does this while the main blocks load, then it shows the page and loads a few more blocks. This can be good for perceived experience, but it can hurt metrics because it causes UI transitions, extra logic, and delays. For example, the LCP metric, which will be discussed later, will be counted when the largest element is loaded, which in this case will happen only after the loader is hidden.

Animations 

Animations sit on a very fine line when it comes to user experience. They are a powerful tool for showing beauty, modernity, and a sense of momentum. And it is true that a site without well-crafted states, effects, and animations often cannot compete.

With states and micro-effects, things are simple: a short, smooth response to every interactive user action. Full animations are more complex. An overabundance often leads to the page freezing or stuttering, especially on a user’s first visit (and since animations are used mostly on marketing landing pages, that is a large part of the audience). You need to find a balance in both quantity and complexity. For especially complex animations, a much more efficient solution is often to use video.

There are also cases of deliberately worsening the user experience. For example, full-screen transitions on scroll. Instead of quickly scrolling to the relevant part (pricing, description, the form itself, and so on), the user spins the wheel for 10 seconds and watches animations they do not need.

A similar situation happens with videos or animations that autoplay as you scroll. Users often do not need those videos. Each scroll step should reveal useful information that stays anchored in place.

Image display 

Another basic and controversial example is progressive image loading, where an image is shown first in very low quality with blur, and the full version loads in the background. This is how, for example, Cloudflare Mirage or Next.js Image works. This approach is controversial for a few reasons:

  1. It treats the symptom. If a site has heavy images, they should be optimized, converted to different formats, compressed, resized, and so on (this will be covered in more detail later).
  2. Modern browsers already know how and when to load images. Using JavaScript shifts that responsibility onto the app. It is very hard to replicate all necessary optimizations.
  3. This adds extra requests to the queue. That can be critical. Even if the initial images are very small, a lot of time is usually spent on connection setup and latency. With many images, the request waterfall becomes overloaded.

So, with the right optimizations, this can improve user experience because the user sees thumbnails quickly. But, all else being equal, it will likely worsen speed metrics, because it clogs the pipeline with extra requests (or increases page weight if those images are inlined) and runs inside client logic.

Another common mistake is setting loading="lazy" on a large image in the first section. It will load after all scripts, sprites, CSS files, other non-lazy images, and so on. But the user should see that image immediately, which means it should be much higher in the queue.

I intentionally do not mention image preloading (meta preload) here. It is usually better to load images via picture with multiple formats. With preload, you either have to pick a preferred format or preload all possible variants (which also harms other metrics).picture with multiple formats. With preload, you either have to pick a preferred format or preload all possible variants (which also harms other metrics).

Late image loading affects metrics, especially LCP. Incorrectly configured images can also worsen CLS. That brings us to the main set of metrics: Web Vitals.

Web Vitals 

Web Vitals is a set of metrics that Google considers key to user comfort. Currently, they include:

  • FCP (First Contentful Paint)
  • LCP (Largest Contentful Paint)
  • TBT (Total Blocking Time)
  • CLS (Cumulative Layout Shift)
  • SI (Speed Index)
  • INP (Interaction to Next Paint)

All of these metrics have different weights. You can see the weight and the potential benefit of improving each one in a special calculator.

The list changes constantly. For example, in 2017 there was First Meaningful Paint instead of FCP, Perceptual Speed Index instead of Speed Index, and Estimated Input Latency (which was later replaced by First Input Delay and is now being replaced by INP).

Lighthouse version from 2017
Lighthouse version from 2017
alt

Web Vitals metrics are part of the Lighthouse analyzer. Lighthouse, in turn, is part of the PageSpeed Insights service, which is part of the Google PageSpeed toolkit. The latter was introduced by Google back in 2010.

pagespeed labs version from 2011 — https://youtu.be/_MuVoabSLeY?si=wgEGtAMiQXIMkRNZ&t=2593
pagespeed labs version from 2011 — https://youtu.be/_MuVoabSLeY?si=wgEGtAMiQXIMkRNZ&t=2593
alt

Today this is the main set of metrics for analyzing site performance in Google and on the web overall. But in the first years after release, they were not very popular. Everything changed when Google updated its search ranking policy.

Why Web Vitals appeared 

If you find a first-generation website today, its contents will usually arrive extremely quickly, even though those sites had no optimizations (not even response compression). For example, netside.net has a total resource weight of 117 KB (114 KB transferred). For comparison, the average Wikipedia page is about 750 KB (250 KB transferred), and react.dev/reference/react is about 2.1 MB (915 KB transferred).

At the same time, both Wikipedia and the React documentation load in roughly the same time as netside on fast connections, but on slow connections they take 2 to 3 times longer for the full content to appear (8 seconds versus 3 seconds).

The internet got much faster, and as a result people largely stopped paying attention to page weight. Today, an apparently simple text page can load tens of megabytes of data. Services that are identical in complexity, with medium-sized HTML, simple styling, and basic logic, can still differ dramatically in size and metrics.

While some teams built huge products and optimized them to load in a couple of seconds, others simply scaled sites to tens or hundreds of megabytes. jQuery, Angular, and later Vue and React accelerated this trend to extreme levels.

As a result, users increasingly landed on sites that took longer than 3 seconds to load. Without waiting for the content, they would go back to search and try other sites. At some point Google noticed this. After being disappointed a few times, users could close the search engine or switch to another one (where results were ranked differently).

In 2020, the Web Vitals metric set was fully introduced, Lighthouse was rebranded, and a new era of optimization began. Metrics returned to the web with renewed force.

Impact of metrics on business 

In 2020, not only the metrics themselves were introduced, but also updated tools for analyzing and optimizing them. Lighthouse did not just show a page’s results. It provided clear, concrete metrics, instructions, and documentation for possible optimizations.

Today, metrics play an important role in search results. Slow sites risk more than just the three-second rule. They can also lose organic traffic as they drop in rankings. But why?

Google, of course, does not disclose all ranking rules, and it often says it does not know them in full. Still, it is known that a position in search results is the sum of many factors. Some factors are higher priority than others. Content quality, relevance to the query, and a site’s overall “weight” are among the most important. But Web Vitals metrics are also one of the ranking factors.

At the same time, an even bigger factor is how real users behave. That is why, in Google, many metrics are assessed using real user data rather than purely in a lab. If people visit a site and consistently stay on it (instead of immediately returning to search), that is a good signal. So if a site is slow, it not only loses points on metrics. It also risks losing overall effectiveness. Some sites can have very poor performance metrics while still being highly effective. Such sites can rank above sites with good metrics but worse user effectiveness, because this factor matters more.

Overall, this started an era of chasing metrics and endless attempts to trick Google. For example, for a while it was popular to show crawlers a screenshot of the first screen. Agencies often used this approach. The image loaded much faster than all of the site’s resources, so the metrics were immediately counted. It is possible that approaches like this are exactly why performance is now analyzed using real user data. Today, if Google sees suspicious differences between what bots and real users receive, it can react harshly. This often means removing pages from search results and blocking them in Google’s services.

Of course, slow sites also affect the business itself. Tasks take longer to complete, navigation is slower, and various unpleasant effects appear. Overall, it is simply less comfortable for people to use such a site.

A few more resources on how optimizing metrics can help a business:

How The Economic Times met Core Web Vitals thresholds and increased overall bounce rate by 43%

How redBus improved Interaction to Next Paint (INP) and increased sales by 7%

How Renault reduced bounce rate and improved conversions by measuring and optimizing Largest Contentful Paint

BBC found that they lose an additional 10% of users for every extra second a website takes to load

Vodafone: improving LCP by 31% increased sales by 8%

Rakuten 24: investing in Core Web Vitals increased revenue per visitor by 53.37% and conversion rate by 33.13%

Metrics for dynamic sites 

Over time, a number of single-page application (SPA) libraries and frameworks started being used to build marketing websites. As a result, a large share of content ended up outside the reach of search engines. Google reacted again. Googlebot began not only scanning sites immediately, but also letting dynamic content render. This meant apps could fully compete for rankings.

How Google processes JavaScript - https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics
How Google processes JavaScript - https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics
alt

This means the question of metrics also affected these tools. Frameworks started competing not only on simplicity and features, but also on speed. But they did not do a great job at it. Splitting logic, lazy loading, style optimization, and deferred rendering can, in the case of marketing landing pages, only get you closer to native sites.

An SPA can apply many internal optimizations only after all client logic has loaded. That makes sense for web applications, because it brings a large benefit for long browsing sessions and repeat visits. But for landing pages, optimizations for a user’s first visit are often much more important.

Today, React Server Components are changing this. Combined with many built-in optimizations in React and Next.js, they make it possible to get comparable metrics out of the box and provide a lot of potential for marketing use cases. But that is a topic for separate articles.

Data collection and analysis 

Overall, metrics are important, metrics are useful, and metrics need to be improved. But before improving them, you need to collect data about them.

Lighthouse 

The first tool on this list is the already mentioned Lighthouse.

Lighthouse is the main tool for working with Web Vitals in lab conditions. It lets you collect the metrics themselves, look at additional factors (such as accessibility or best practices), find weak spots, and review recommendations for improvements.

You can test a site in Lighthouse both locally and via the PageSpeed Insights service, on the recommended device.

If you need a quick check for the main issues, it is enough to run the local version (Developer Tools → Lighthouse → Analyze Page Load). If you need a full analysis, trend tracking, and more stable results, use PageSpeed Insights. The service will show all the needed information, but specifically on the recommended device. Also, if the site is popular enough, the service will show average user metrics.

Developer tools 

Besides Lighthouse, DevTools has a number of other useful tabs, but the most helpful for optimization are probably Performance and Network.

Performance

Performance lets you record a page profile, including resource loading, script execution, and rendering.

In this tab you can immediately see FCP and LCP. You can check request queues, analyze long scripts and animations, see delays, and find overloaded moments.

Network

In the Network tab you can see all network requests, including loading resources (images, scripts, styles) and REST requests. This helps identify which resources slow down loading.

Here you can see the load time of each resource (including request latency), the request waterfall, queues, drops, request order, size, and caching.

Waterfall of https://en.wikipedia.org/wiki/Northern_Hemisphere

Search Console 

You can get a bit of additional information about real user metrics from Search Console.

Google Analytics 

This may be an unexpected service on the list, but it is one of the most effective for analyzing real user results (Real User Monitoring, or RUM). GA can collect any data by simply enabling the needed options in settings, sending additional metrics manually, or connecting a ready-made preset in GTM (Google Tag Manager). For Web Vitals there is also a ready-made preset. Once connected, GA will start receiving all the metrics data you need.

All that is left is to build charts and start tracking trends.

Third-party services 

DebugBear

DebugBear lets you automatically collect and analyze metrics through several tools, including Lighthouse, run multi-run analysis (to get more accurate metrics), and track and compare metrics and requests over long periods of time.

SpeedCurve

SpeedCurve lets you analyze real user metrics, test from different browsers and locations, check performance in CI/CD, analyze INP, and more.

GTmetrix

GTmetrix lets you analyze under different conditions, replay video recordings, test different scenarios, and analyze request waterfalls.

Site24x7

Site24x7 lets you monitor all server components, from site load speed to network and Kubernetes monitoring, from more than 130 locations worldwide.

Pingdom

Pingdom lets you monitor a service, including availability and response time analysis. You can configure outage alerts and analyze from many locations. It can also monitor specific user scenarios.

Uptrends

Uptrends offers availability, performance, and infrastructure monitoring. It includes analysis from different locations, detailed reports, scenario testing, and API monitoring.

WebPageTest

WebPageTest lets you analyze a site and then validate optimizations using dynamic tests. The service can also be used to pre-check planned changes (for example, adding third-party analytics).

Metrics optimization 

So, we have learned what metrics exist and how to analyze them. That means it is time to move on to optimizing them.

Image optimization 

This is the improvement already mentioned in the context of user experience. Images often take up a significant share, not only of the page content, but also of its weight, meaning transferred traffic. That means it is worth reducing their weight. There are several approaches.

Image compression

The first and most obvious solution is to compress the image. There are many services and tools that can reduce image size, sometimes significantly, without a visible loss of quality.

Image before and after 80% compression

Overall, there are many solutions, and that deserves a separate article. In general, there are a few paths:

  • Compress manually using web services or dedicated tools.
  • Compress during the build.
  • Compress dynamically via a third-party service or the application backend.

Resizing images

If an image is used in a 400x200 block, it does not need to be 1920x1080. No screen will show that level of detail in such a small block. It is better to use an image that is no more than 2x the display size. This margin is useful, for example, for retina displays.

- <img style="width:200px" src="/example_1920x1080.png"></img>
+ <img style="width:200px" src="/example_400x225.png"></img>

Lazy loading

The idea of lazy loading is to defer downloading files until they are needed. For images, that is until they are visible.

First, it is worth using the native browser attribute loading="lazy". It gives the desired result on fast connections. On slow connections, all images can still be queued immediately, so that when scrolling the page the user does not encounter blank spaces. But those images go to the bottom of the pipeline, letting the user load the most important files first, and only then load images.

<img style="width:200px" src="/example_400x225.png" loading="lazy"></img>

It is important that this attribute should not be used for critical images, such as a large image in the first section, meaning LCP.

Using modern formats

Among modern formats, webp and avif are worth mentioning. Both have good support today, and it is likely broader than what your website supports. At the same time, it is hard to say which format is optimal. For each image, the compression ratio and quality trade-offs differ. For example, for illustrations, png can often weigh less than a modern webp. For text, avif works well. For raster images with transparency, webp often works well.

On average, choosing the right format can reduce image weight by more than 50%.

Serving different images

If someone visits from a mobile device, they do not need images intended for desktop, neither in size nor in quality. On mobile devices there is much less space for an image and often lower display capabilities.

The most convenient way to serve different images depending on conditions is to use the <picture> tag. It lets you specify which image to show for which screen size and type.

<picture>
<source srcset="/example_800x450.webp" media="(min-width: 1080px)" type="image/webp" />
<source srcset="/example_800x450.png" media="(min-width: 1080px)" />
<source srcset="/example_400x225.webp" type="image/webp" />
<img src="/example_400x225.png" loading="lazy" />
</picture>

A nice bonus is that picture can include multiple formats. For example, webp as the primary one and png as a fallback for the rare case when webp is not supported or is disabled for some reason.

Serving different images in CSS

For CSS background images, handling screen size is simple: define media queries and set background-image to the right variant. But format selection is harder. For these cases, you can add a blocking script at the start of the page that adds the required classes to the whole document, such as .img-webp and .img-2x, and then set images in CSS based on those classes.

.example-block {
background-image: url("/example_400x225.png");
}

.webp .example-block {
background-image: url("/example_400x225.webp");
}

Sprites

For large images, the main goal is to reduce weight. For small images, the main goal is to reduce the number of requests. Small images and icons often weigh so little that transfer time is not the main issue. Instead, much of the time goes into connection start and subsequent delays. At the same time, a page often contains dozens or hundreds of icons. All of them can overload the pipeline and prevent important information from loading.

image.png
alt

The best solution in this case is to combine all icons into a single file, a sprite. This can be an SVG or a PNG.

With SVG, an svg sprite is created as a single svg file, where each icon is defined as a separate <symbol /> tag.

<svg xmlns="<http://www.w3.org/2000/svg>">
<symbol viewBox="0 0 24 24" id="check">
<path d="M20 6L9 17L4 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
<symbol viewBox="0 0 24 24" id="close">
<path d="M17 7L7 17M7 7L17 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
</svg>

Then it is used via the use tag.

<div>
<svg width="20" height="20">
<use href="/sprite.svg#check"></use>
</svg>
</div>

Critical icons, if any, can be split into an additional sprite and inlined into the HTML.

With PNG, or another raster format, you create classes that crop a specific icon out of a larger image, a CSS sprite. This approach is often used by maps.

.icon {
background: url("/sprite.png");
height: 20px;
width: 20px;
}
.icon-check {
background-position: 20px 0px;
}
.icon-close {
background-position: 40px 0px;
}

Inlining images

Another possible optimization for small images is to inline them. This is useful when small images are used once and only on a single page. If the image repeats, it is better to include it in a sprite. This is usually implemented via additional loaders and special file naming.

Video optimization 

The main improvement for video is deferred loading. But unlike images, it often follows a more progressive path:

  1. A preview image is shown instead of the video at first.
  2. When the pipeline frees up, or on hover over the preview, the player logic starts loading.
  3. On click of the preview or the play button, the actual video starts loading and playing.

In some sections, YouTube shows GIF previews on hover, and on click navigates to the full player.

Static compression 

A key optimization is configuring compression. Compression is especially useful for JS, HTML, and CSS files. It can reduce transfer size by around 50% to 70%, more or less depending on compression level, file size, and content.

You can compress files during the build, generating brotli or gzip versions. It is better to prefer brotli, because it is about 20% more effective than gzip.

More often, compression is delegated to a CDN or the server, in many cases nginx. But with incorrect configuration, such as missing caching, this can increase server response time.

Style optimization 

How styles are delivered

There are three ways to deliver styles to a page:

  • inline, where styles are written on the element via the style attribute.
  • embedded, where styles are written into the document in a <style /> tag.
  • external, where styles are loaded as a separate file.

Inline inflates the document, and that is critical, so it is not suitable as the main approach in most cases. External allows caching. But if every page has unique styles and the visitor only comes once, that benefit disappears. Embedded is most effective when each page has unique styles and you use streaming.

Optimizing style application

When rendering a page, changing DOM elements, or changing an element state, such as hover or focus, the browser recalculates styles. In some situations, this can cause visible slowdowns.

As basic optimizations, remove unused styles and move rarely used media into separate bundles with conditions.

<link
rel="stylesheet"
href="mobile.css"
media="screen and (max-width: 600px)"
/>

Optimizing selectors

This is a less obvious optimization. Evaluating some selectors can be an expensive operation. For example, if you have a selector like body.test-a .block[data-test=a], when the body class changes the browser needs to match all .block elements on the page.

  • Reduce selector complexity, for example by scoping to a specific section rather than the entire body.
  • Reduce the number of potential matching elements, for example by using a more specific class rather than a common one like block.
  • Avoid unnecessary selectors, for example if the current page does not have that test at all.

More about optimizing and debugging selectors can be found here: https://developer.chrome.com/docs/devtools/performance/selector-stats?hl=en#analyze-stats.

Deferred rendering 

In addition to lazy loading sections or deferring rendering via JavaScript, you can use a standard CSS mechanism. The content-visibility property lets you tell the browser an element's visibility on the page.

By default, all elements are rendered immediately and are fully available. But if you override this property, the browser can optimize rendering. With auto, the element will be prepared and rendered as needed. With hidden, it will remain hidden until you change the value.

.map {
content-visibility: auto;
contain-intrinsic-size: 1000px;
}

The contain-intrinsic-size property lets you reserve height for the element. This is similar to height for an img with loading="lazy".

It is important to note that if you set hidden, the element will not be available to bots or for in-page search.

Font optimization 

Fonts are often a weak spot for a website because they are both critical and fairly heavy resources.

Optimizing the glyph set

First, review the fonts used on the page. Are all font families, weights, and variants really needed. After keeping only what is necessary, or switching to variable fonts, you can move on to optimizing how fonts are loaded.

@font-face {
font-family: "Inter";
src: url("Inter-Regular-webfont.woff2") format("woff2");
unicode-range: U+0025-00FF;
}

Loading strategy

There are two main approaches to font loading:

  • Render-blocking font loading. With this approach, the page content starts displaying only after all fonts have fully loaded.
  • Non-blocking font loading with a fallback. The fallback is the font used while the main font is loading, or if the main font fails to load. With this approach, the user sees the page content immediately. However, once the font loads, it replaces the fallback, which can cause layout shifts and an unpleasant experience.

Which approach to choose depends on the situation, since both have pros and cons.

In some cases, teams also use background font loading and apply those fonts only on subsequent visits.

Preloading

Another possible improvement is preloading fonts. This moves the font earlier in the loading pipeline than other resources.

<link rel="preload" href="/Inter-regular.woff2" as="font" type="font/woff2" crossorigin>

This step, like many others, can have negative side effects. For example, secondary fonts can take up the network pipeline, while the hero image from the first section ends up at the bottom of the initial request queue (so it is important to limit the number of fonts and preload only critical ones).

Faster server response 

Because resources load like a train, one after another, server latency has a compounding effect. For example, if server latency is 60 ms and the hero image from the first section is loaded via JavaScript, it will load 120 ms later than it would with 20 ms latency (40 ms latency for the HTML, then 40 ms for the script, then 40 ms for the image).

At the same time, latency stretches the entire pipeline and, as mentioned earlier, this is especially important for small files.

To reduce latency, the following can help:

  • Using static compression instead of dynamic compression.
  • Optimizing server logic (for example, middleware chains or poorly optimized rewrite and redirect handlers).
  • Using a CDN. The user is served by the nearest edge location, not a server on the other side of the planet.
  • Upgrading the transport protocol (HTTP/2, HTTP/3).
Protocol comparison by Maria A. - https://www.cloudpanel.io/blog/http3-vs-http2/#:~:text=4. Connection Establishment Time

Caching 

The best way to optimize requests is to avoid requests. One way to do that is caching.

When all parts of the page are already downloaded and stored, the browser only needs to render the page (which takes relatively little time). Caching can dramatically speed up repeat page loads and navigation to subsequent pages (since some resources are shared).

Caching usually relies on:

The Cache-Control header. It lets you set how long the browser can cache a response. This should only be used together with a hash in the filename. Otherwise, the user may be unable to get updated resources (which can lead to unexpected artifacts).

The Etag and Last-Modified headers. They let browsers detect whether content has changed and only download the file if it has. Otherwise, the browser uses the cached version. This approach requires an additional request to the server, which adds latency. For that reason, Cache-Control should be the default choice, and Etag or Last-Modified should be used for special cases.

Other 

Reducing layout shifts

Another important improvement that affects how fast a site feels is reducing layout shifts (CLS). They can happen, for example, when a user loads a page [and may have even started using it], and then additional elements load and shift the entire UI. These can be banners, images, dynamic widgets, and so on.

For most cases, the main solution is to reserve the most accurate amount of space for the block. For example, for a banner above the header you can fix a minimum height of 60 px on desktop and 120 px on mobile. For images, use built-in mechanisms:

  • Set width and height so the browser can infer aspect ratio and reserve the right space for the current container.
  • Set aspect-ratio in CSS.

Avoiding render-blocking elements

Some elements can completely stop rendering and further processing of the page. These are called render-blocking. Until they load and or execute, loading of required resources and showing the page content is blocked.

These elements commonly include:

  1. Inline styles and scripts (inside <style> and <script> tags).
  2. <link /> elements in <head /> (for example, <link rel=stylesheet href="...">).
  3. External <script /> tags without defer or async.

Postscript 

Beyond the list above, there are dozens or hundreds of other optimizations. Every framework, every library, and every integration has its own issues and its own impact on metrics.

As mentioned earlier, every optimization is analysis, checks, tests, and searching for the best solution for a specific case. Validate ideas and continuously track trends. The best thing you can do is fix losses in time.

Replies

No replies found