Performance
Optimising your site for performance can result in higher SEO ranking, improved user experience and greater conversion rates. Core Web Vitals are metrics used to measure the performance of a site.
This guide details serveral ways to improve your Altitude website performance.
General Performance Improvements
Cache Expensive Components
Components relying on complex queries (e.g. page header / footer) which typically have slower response times may be cached for longer than the rest of the page.
In order to reduce the call rate of the header / footer gql query, the response is cached in Cloudflares cache via the Cache API.
When a page receives a cache MISS, the header / footer response is looked up in the cache and if found, the response is then used to render the component without the need to call the origin improving TTFB.
---cache = caches.default
// Request is used as the cache keycacheKey = new Request(`${horizonEndpoint}/${host}/headerfooter`, { method: 'GET'})
response = await cache.match(cacheKey)---
Adding to the cache
When a response is not found, the header / footer is queried from the origin. Additional headers are then added to the response, such as the TTL before being put into the cache. The intention is that next time there is a cache MISS on a page, the header / footer should recieve a cache HIT from the Cloudflare cache.
---if (!response) { response = await fetch(`${horizonEndpoint}/graphql`, { method: 'POST', body: `{ "query": "${HeaderFooter}" }`, signal: AbortSignal.timeout(5000) })
response = new Response(response.body, response)
//Below headers need to be deleted to make the response cachable response.headers.delete('Set-Cookie') response.headers.delete('Expires') response.headers.delete('surrogate-control') response.headers.append('Cache-Control', 'max-age=600')
await cache.put(cacheKey, response.clone())}---
Efficient Horizon Calls
Make only one Horizon call per server call (with exception of separately cached components such as header/footer).
Enable Cache Sheilding
Cache shielding reduces load on origin servers and improves content delivery speed by positioning an additional cache layer closer to users.
Use Image Processing
More details available here.
Designing for Performance
Designing a website for web performance is an often overlooked area for optimisation. Here are a few good examples of where design patterns can impact performance and how to address them.
Third-party Features
Utilising features provided by third-party platforms (for e.g. PowerReviews, Qubit, BazaarVoice, StoryStream) that do not have APIs backed features and functionality require special consideration to ensure they’re performant. Typically these vendors require a process of hydrating elements into the page after page load. Often creating a Cumulative Layout Shift (CLS) risks alongside a risk of Total Blocking Time (TBT).
In cases where features ‘hydrate’ into the page it’s important to asyncronously load these elements and defer their load to avoid hindering the load of the other critical element in a page. While this defers JavaScript (and reduces the risk to latency in parsing the more critical JavaScript) the increased delay to display a feature can then worsen CLS as the page is at risk of needing to recalculate layouts.
Where possible, changing how we approach the load of these vendors is recommended and avoiding assets that load after a page load. Delay vendors loading until the customer provides intent indicators (e.g. click, hover, scrolling into view) will improve the performance drastically.
Here are a few commerce examples of this:
User Capture / Form Inputs
Google reCaptcha (or similar products) are often needed on form inputs to prevent brute force bot attacks. However the performance implication of reCaptcha loading in initial load of the page is very high. If there is a form on site in a low priority part of the page (e.g. an email newsletter sign up in the footer), it is typically best to push these to forms into a modal that the user needs to manually open. This will defer the need for a reCaptcha until after the user interacts with the relevant area of the site.
It’s also important to consider reCaptcha performance if your commerce brand utilises entry modals (e.g. to capture email subscriptions). Deferring the load of reCaptcha until you’re able to determine that the customer intends to interact with the form (rather than on initial load) is a perfect example of where loading vendor features after confirming intent has significant impact.
Live Chat
While customer support is an important pre-sales and after-sales service. It’s common for providers offering live chat / web messaging features to be network and computationally heavy element. Creating a slow experience for all users and risking SEO ranking if not managed appropriately.
Case Study
Astro Framework
Disable Streaming
Disabling streaming offers some significant performance improvements. Refer to the Astro framework guide for more details.
GraphQL Raw Imports
Using raw GraphQL imports can lead to a reduced TTFB latency as the parse times for the .gql
files are quicker.
---import CollectionPage from '@graphql/queries/CollectionPage.gql?raw'---
There is, however, a trade-off as raw imports are not compatible with GraphQL fragments, as the raw import as text skips the GraphQL loader.
Set HTTP Cache Headers
HTTP cache stores web content to reduce server load, decrease loading times, and enhance overall web browsing efficiency for users.
Within Astro you can do this by setting the header on the response.
Astro.response.headers.set('Cache-Control', `max-age=0; s-maxage=${cacheTTL}`)