Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Home page loads in ~11MB of images, ~13MB of JS #6254

Closed
eatyourgreens opened this issue Aug 30, 2024 · 18 comments
Closed

Home page loads in ~11MB of images, ~13MB of JS #6254

eatyourgreens opened this issue Aug 30, 2024 · 18 comments
Labels
bug Something isn't working

Comments

@eatyourgreens
Copy link
Contributor

eatyourgreens commented Aug 30, 2024

Expected behavior

Images should be optimised for display online, and the home page should ideally load in less than 1s.

Current behavior

The home page pulls in a bunch of unoptimised images from the Zooniverse blogs, ranging in size from 0.5MB all the way up to a whopping 7.5MB! Even on fibre broadband, the page takes 11s to fully load.

These images in particular could benefit from being resized for display online:

Steps to replicate

Examine the overall page weight and image sizes in the Network panel of the browser dev console.

Image sizes for the Zooniverse home page, in the Firefox Network panel.

Signed-out, the home page also loads in more than 10MB of YouTube JS, for a total page weight of 31MB.

JavaScript download sizes, ordered by size, for the signed-out Zooniverse home page in the Firefox Network panel.

Additional context

Here's a page speed report, including Core Web Vitals:
https://pagespeed.web.dev/analysis/https-fe-root-preview-zooniverse-org/xk3wjubq40?form_factor=mobile

It's a failure on both desktop and mobile, but includes a list of steps you can take in order to pass. It estimates that you can reduce image sizes by at least 6MB.

The new page renders entirely in the browser and is also much slower than the old home page:

@eatyourgreens eatyourgreens added the bug Something isn't working label Aug 30, 2024
@eatyourgreens
Copy link
Contributor Author

eatyourgreens commented Aug 30, 2024

One of the reasons that the new page is slow, is that isLoading here is always true on the server, so rendering of the whole home page (including static content like the list of blog posts) is deferred to the browser:

{isLoading ? (
<Box as='main' height='100vh' align='center' justify='center'>
<Loader />
</Box>
) : (

This also means that the page scroll position is lost when navigating backwards and forwards, since the scroll position refers to the height of the server-rendered Loader component (#6208.)

Here's the new home page in Firefox, with JS disabled. This is what a user will see if they're on a flaky connection and one of the JS files errors while it's downloading.
This is also how search engines and social media bots will see the home page.
The new Zooniverse home page in Firefox with JS enabled, showing just a loading spinner that will never complete.

@eatyourgreens eatyourgreens changed the title Home page loads in ~11MB of images Home page loads in ~11MB of images, ~13MB of JS Aug 30, 2024
@eatyourgreens
Copy link
Contributor Author

eatyourgreens commented Aug 30, 2024

Paul Irish's lite-youtube-embed has a couple of React ports that won't use 2.5MB of JS per video. It's probably quite easy to write your own lightweight React YouTube embed too.

EDIT: There's a lite-youtube-embed React wrapper for Next.js. It's distributed with @next/third-parties. It's only 30 lines of JS!

@seanmiller26
Copy link
Contributor

@eatyourgreens I went ahead and resized the penguin photo. I didn't bother to optimize the other 2 as they soon will be pushed off the feed by new posts. This is a good reminder to optimize our image sizes before uploading to the blogs.

@eatyourgreens
Copy link
Contributor Author

@seanmiller26 👍 The penguin image looked like it had been uploaded straight from someone's iPhone. I'm surprised that Wordpress doesn't automatically resize images for the blog RSS feeds.

Longer term, it should be straightforward to add rules to https://github.com/zooniverse/thumbnailer/ that allow it to resize images from daily.zooniverse.org and blog.zooniverse.org.

@eatyourgreens
Copy link
Contributor Author

If you want to test this in a browser, I recommend setting throttling to either 4G or 'slow 4G', which is apparently representative of rural network speeds in the USA.

For a more in-depth write-up of JS-first performance and its disproportionate effect on the least privileged members of society, read Alex Russell's excellent Reckoning series of posts. Simon Willison summarised it in a single page too.

@eatyourgreens
Copy link
Contributor Author

@seanmiller26 I've added lazy loading in #6255, so that blog images aren't loaded unless you scroll down to that section of the page.

@eatyourgreens
Copy link
Contributor Author

eatyourgreens commented Sep 17, 2024

Now that #6255 has merged, Core Web Vitals for the home page are looking a lot better. Total blocking time: 0.13s, speed index 2.6s on desktop. Mobile is still pretty slow. Total JS jize is ~1.5MB.

Page Speed Insights also reports that static images served from panoptes-uploads.zooniverse.org and static.zooniverse.org haven't got caching headers set, so they're being refetched on every visit.

A section from the PageSpeed Insights report for the new home page, listing Zooniverse images that are served without caching headers, including project avatars.

@goplayoutside3
Copy link
Contributor

@eatyourgreens the homepage is no longer loading the weight described in the Issue title, but before I close it I want to follow-up with your point about:

static.zooniverse.org haven't got caching headers set, so they're being refetched on every visit.

Correct, custom headers have not been set in img files such as https://static.zooniverse.org/fem-assets/green-pea.jpg. When I visit https://www.zooniverse.org/about, "refetched" means fetched from the CDN. Are you suggesting adding custom headers via Next.js config to single out image files in static.zooniverse.org so the browser can cache them?

We're actively working on an overall cache busting strategy for the Zooniverse website especially now that Next.js is being used to build static pages like /about, and not just dynamic pages like /projects/etc. Cache busting AFD on deploy of a new app build will happen, but that's only for www. Adding custom headers to image files in static.zooniverse.org will require additional work to handle any changes made to files at static.zooniverse.org.

@eatyourgreens
Copy link
Contributor Author

Correct, custom headers have not been set in img files such as https://static.zooniverse.org/fem-assets/green-pea.jpg. When I visit https://www.zooniverse.org/about, "refetched" means fetched from the CDN. Are you suggesting adding custom headers via Next.js config to single out image files in static.zooniverse.org so the browser can cache them?

I imagine headers for those files would have to be set either by nginx or Front Door. static.zooniverse.org isn't handled by Next.js.

Here's the explanatory link from the Lighthouse report.

https://developer.chrome.com/docs/lighthouse/performance/uses-long-cache-ttl/

@eatyourgreens
Copy link
Contributor Author

eatyourgreens commented Oct 3, 2024

Here's a more up-to-date report. Total network payload on desktop is still 10MB. Mobile is 1.1MB so I guess most of the desktop payload must be the video.

I think mobile's failing the performance test because the loading animation delays LCP, and anything over 4s is a fail.

@eatyourgreens
Copy link
Contributor Author

The browser isn't caching the home page video on desktop. That's going to be a big performance hit, since it has to be fetched on each visit to the home page.

Each file listed here should be loaded from the browser cache, if possible, for the fastest home page experience.

A list of uncached home page assets, from Page Speed Insights a, including two video files totalling about 7.5MB.

@eatyourgreens
Copy link
Contributor Author

eatyourgreens commented Oct 4, 2024

Removing the .webm video would save a lot of bandwidth too. Are there any browsers left that don't play MP4/H264? Also, it's odd that the WebM video is 2.5 times bigger than the MP4 file. WebM should give much better file compression.

@eatyourgreens
Copy link
Contributor Author

By the way, when Google recommends setting efficient Cache-Control headers for 19 static files here, 10 of the URLs are YouTube URLs, where the caching policy is set by Google. 🤦‍♂️

Exceprt from a page speed report for the Zooniverse home page, listing static resources that have no or short cache lifetimes set.

@eatyourgreens
Copy link
Contributor Author

eatyourgreens commented Oct 6, 2024

@goplayoutside3 by the way, https://www.zooniverse.org is still sending an invalid Cache-Control: s-maxage=3600, stale-while-revalidate response header. I thought that particular bug had been fixed in Next.js. See vercel/next.js#51823 for details.

Looking at the PR that fixed that bug (vercel/next.js#61330), you might need to add nextConfig.experimental.swrDelta to your app config.

https://dev.to/omaiboroda/stale-while-revalidate-and-its-usage-with-nextjs-55c7

@goplayoutside3
Copy link
Contributor

Files in http://static.zooniverse.org/fem-assets now have cache control public, immutable, max-age=604800 via FrontDoor. It might take a while to see the updated headers because they previously didn't have custom headers set, so AFD randomly picked “a cache duration between one and three days.” (https://learn.microsoft.com/en-us/azure/frontdoor/front-door-caching?pivots=front-door-classic#cache-expiration)

@eatyourgreens
Copy link
Contributor Author

eatyourgreens commented Oct 14, 2024

Sounds cool. 👍 Google also complained about static files from panoptes-uploads, but I don't have a good sense of what would be a good cache lifetime for those. If each uploaded avatar has a different filename, then those files can probably have cache lifetimes of a year or so. At least, that's what we set for the project app JS files.

@eatyourgreens
Copy link
Contributor Author

By the way, I think the original issue here, which was the large YouTube JS and the large blog images, has been fixed. So feel free to close this and open issues for other performance recommendations from the Google page speed report.

@goplayoutside3
Copy link
Contributor

Agreed. I'm starting to see expected cache headers on images fetched from the /fem-assets folder in blob storage. I'll ask Zach how he feels about cache headers on panoptes-uploads too.

There are still a couple of your comments that have not been addressed, but are scoped to #6344.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants