A little while ago I wrote a post about speeding up the landing page for Tesla's Cybertruck, inspired by Jake Archibald's performance reviews of F1 sites. Looking at the things that are slowing down a page can be a useful way of learning what to avoid, and can teach you how to improve those things.
This time, I wanted to see if I could improve site speed for the supplier of everyone's favourite childhood memories: Nintendo.
I did this on a test build of their site where I cloned the HTML - they're (sadly) not a client and I don't work for them.
One disclaimer before I dive in. There are lots of reasons for why sites might not be perfect - often the developers who work on the site are aware, but there might be lots of reasons for why they don't have the time or resources to work on fixing them. This isn't an attack on anyone, no site is perfect - this is purely to explore how a page could be sped up.
What we're trying to improve
The highlighted image below is the Largest Contentful Paint element (or at least, it is for the viewport of an iPhone 11 - and probably most mobile devices), so that's what I'm going to focus on. That said, I also want to improve the time it takes for the page to start rendering.
Don't lazy load above-the-fold images
Nintendo lazy load their images, so the browser only requests them just before they scroll into view. Lazy loading is great for images that are below the fold, but our goal is to have the above-the-fold images render as quickly as possible.
<img> tags for the above-the-fold images, which meant the browser was able to see and request those images much earlier.
Remove the anti-flicker snippet
The Nintendo homepage uses an anti-flicker snippet, which was delaying rendering. These are usually in place for when a site is running A/B tests - users might see the control headline, or call-to-action, or whatever it is that's being tested swap from the control to the variant. A/B software sometimes suggests an anti-flicker snippet to solve this problem: it shows a blank white page until the A/B test has loaded, or 4 seconds have passed - whichever comes soonest.
But that's quite a brutal way to solve that problem, especially because Google recommends having your LCP element render in under 2.5 seconds. I solved this by deleting that anti-flicker snippet. I found removing the snippet led to a noticeable improvement in the time it takes for the page to start rendering, particularly on a slow connection.
Remove the legacy Typekit CSS request
I noticed there was a CSS request in the
<head> for a Typekit resource, which then itself loads another CSS file. This is render blocking, so the browser has to wait until it's downloaded both files before it starts painting anything to the screen.
We can see this from a WebPageTest waterfall - there are two render-blocking Typekit requests, one after the other.
This could definitely be improved, but I noticed that the page doesn't seem to be using any font files from Typekit anyway, so this was a pretty easy fix: I removed the Typekit request. I suspect this is a legacy thing - the site may have used Typekit on an earlier version, and they seem to now have switched instead to Google Fonts (more on this later).
Alternatively, they might still use Typekit elsewhere on the site - in which case, they could instead look to only include the Typekit request on those pages that use it.
Don't use @import in CSS
There's a couple of examples where a render-blocking CSS file uses @import to load in another CSS file. As an example, this CSS file has an @import for a Google Fonts CSS file.
This is slow because it means those render-blocking CSS requests occur sequentially, when you really want all of your CSS to load in parallel as much as possible.
We can see from the waterfall that the Google Fonts CSS file is only requested after the
bootstrap_rd.css file has been downloaded and parsed.
I always recommend avoiding using @import - you can have that CSS load in parallel by using a regular
<link rel="stylesheet"> tag in the initial HTML instead.
And while we're at it, self-host those Google Font files
I love Google Fonts for the speed at which it lets you try out different fonts, and it's great for development, but the Google Fonts CDN comes with a performance cost. When you request the CSS from their server, the browser has to spend time setting up a new DNS/SSL connection to the
fonts.googleapis.com domain, and then again to the
This setup time can take anywhere from 100ms to (on slow connections) more than a second. When we tested it, we found that using the Google Fonts CDN could slow down Largest Contentful Paint by 1.3 seconds on a 3G connection. Instead I recommend self-hosting your Google Fonts.
Compress images and use WebP
Some of the images on the page had a pretty large file size, in particular the first two that appear above-the-fold on a mobile viewport. The main above-the-fold image weighed 182kb, and the image below it was 235kb. That's a little on the high side, so I ran them through Squoosh and converted the JPGs to WebPs which brought the file sizes down to a more reasonable 71kb and 85kb.
Lazy load the images in the side panel
Nintendo's homepage on desktop has a side panel featuring some upcoming games, along with several thumbnail images.
In my test build, I fixed this by adding the
loading="lazy" attribute to the
Defer the script tags at the bottom of the page
This likely has quite a small impact here - but there were a few
I added the
defer attribute to the
<script> tags at the bottom of the page, largely because they were parser blocking, and I wanted to see if I could get the browser to prioritise loading some of the other, more important resources. Nothing seemed to break, but this is the sort of change that really needs a dev team who understands the codebase to test it thoroughly.
Preload the LCP image
And finally, because I really wanted the browser to load the LCP image early, I added it as a
Nintendo serve images with different dimensions depending on the screen size (which is good!), so for them to fully adopt preloading images here, they could use media queries in order to preload the correct size. You can find out more about preloading responsive images here.
What's the result?
Here's what it looks like when testing an unaltered copy of the Nintendo homepage compared to a version where I've made the above changes (on a 3G connection, using an emulated iPhone 8).
The improved page starts rendering and is visually complete in half the time. And importantly, these changes resulted in a Largest Contentful Paint improvement of 58%.