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

feat: preload #41

Open
leoj3n opened this issue Mar 5, 2024 · 2 comments
Open

feat: preload #41

leoj3n opened this issue Mar 5, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@leoj3n
Copy link
Contributor

leoj3n commented Mar 5, 2024

Here is something that may be possible in the future as a browser feature but maybe someone has an idea how to do it now...

If not using the picture element, something like the following is possible to preload sizes and srcset of img:

<svelte:head>
	{#if preload}
		<link
			as="image"
			rel="preload"
			fetchpriority="high"
			imagesizes={sizes}
			imagesrcset={srcset}
		/>
	{/if}
</svelte:head>

For an image like that:

<img
  alt="cat"
  width="640"
  height="640"
  loading="eager"
  fetchpriority="high"
  src="path/to/jpg-640"
  sizes="
    (min-width: 50rem) 23rem,
    (min-width: 43.875rem) calc(100vw - 10rem),
    100vw"
  srcset="path/to/jpeg-640 640w, path/to/jpeg-1024 1024w, path/to/jpeg-1920 1920w"
/>

However, notice this will only allow to preload one "type" of image.

This actually works well if linking to an endpoint that uses headers to dynamically send back the supported "type" to the browser, and 304 when cache is no-change. This caching strategy always incures a network request which is not necessarily ideal, but it is nice to be able to preload.

For instance when using the Vercel image optimization endpoint by updating srcset to be like that:

srcset="/_vercel/image?url=%2Fpath%2Fto%2Fjpg-640.jpg&w=640&q=99 640w, /_vercel/image?url=%2Fpath%2Fto%2Fjpg-1024.jpg&w=1024&q=99 1024w, /_vercel/image?url=%2Fpath%2Fto%2Fjpg-1920.jpg&w=1920&q=99 1920w"

Supported jpeg/avif/webp image types will be served dynamically which avoids having to use the picture element to tell the browser about the various available "types".

If you wanted to preload sources in the picture element, they say this is possible:

https://web.dev/articles/preload-responsive-images#preload_and_picture

<head>
  <link rel="preload" href="small_cat.jpg" as="image" media="(max-width: 400px)">
  <link rel="preload" href="medium_cat.jpg" as="image" media="(min-width: 400.1px) and (max-width: 800px)">
  <link rel="preload" href="large_cat.jpg" as="image" media="(min-width: 800.1px)">
</head>

Which would be the preload directive for that:

<picture>
    <source srcset="small_cat.jpg" media="(max-width: 400px)">
    <source srcset="medium_cat.jpg" media="(max-width: 800px)">
    <img src="large_cat.jpg">
</picture>

But unfortunately this isn't really what we want, as this only accounts for one "type" at a time ("image/jpeg" in this case). If you wanted to preload for "image/avif" and "image/webp" as well I don't think it would be possible using this method. You wouldn't want to use this method when those other types are enabled as it would cause the jpeg to download in addition to the avif/webp, depending.

I'm wondering if a custom endpoint and single img tag like when using Vercel would be a viable solution for when you want to preload. Otherwise I think you have to just restrict yourself to one format (jpeg), and use the single <img /> tag.

So for now you could easily have a preload option that, when enabled, ignores any provided "types" and injects <link as="image" rel="preload" ... /> into svelte:head. I think that's a reasonable compromise to be able to preload.

As an alternative, you could provide guidance on how to set up an endpoint in SvelteKit that returns the correct image type for the requested image url via header analysis (Accept: image/avif,image/webp,image/apng,image/svg+xml,...). It would need to know how to 304 if the browser has the image cached (If-Modified-Since/Etag).

@zerodevx
Copy link
Owner

zerodevx commented Mar 6, 2024

Thanks for the detailed writeup! Definitely open for discussion.

However, notice this will only allow to preload one "type" of image.

The thing is preloading only shaves off milliseconds, but serving next-gen images is doing the heavy lifting and may save hundreds of kb of bandwidth. There's definitely much opportunity for optimisations though. Will circle back to this.

@zerodevx zerodevx added the enhancement New feature or request label Mar 6, 2024
@leoj3n
Copy link
Contributor Author

leoj3n commented Mar 7, 2024

I was able to up my lighthouse from 89/94 to 99 thanks to preloading, but keep in mind this is for an image the incures the network request 304 dance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants