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

data-sveltekit-preload-data / preloadData - preload Images too #10864

Open
alex-frx opened this issue Oct 12, 2023 · 10 comments
Open

data-sveltekit-preload-data / preloadData - preload Images too #10864

alex-frx opened this issue Oct 12, 2023 · 10 comments
Labels
feature request New feature or request

Comments

@alex-frx
Copy link

Describe the problem

I think it is a little inconvenient that the preloadDat doesn't have a mechanism to preload Images too.
Svelte is focused on DX/convenient/rapid development and today's Website often contain a fair amount of Images. Which often contribute to the overall appearance / content of the website. So it would be nice to have them instantly available once a user navigate -> prefetch them before the user navigates.

I couldn't find a nice solution to implement this atm. I found a few thing that could be done but all fall apart at one place or the other:
1.) Programatically load the images via a Image or <link rel="preload" src="..."/> -> this is somewhat fine and working but depending how you get the images can be some extra amount of work and only works if the server has an cache-policie in place.
2.) Somehow loading the Picture in the load function of +page.server.ts (like a blob an save it to a store or whatever) - this works well but falls apart if the user clicks on links fast and on 'full reloads' because then the function takes time to complete an blocks the ui from appearing. The full reload issue can be fix if one checks the isDataRequest attribute.
3.) I had some more will add later

Describe the proposed solution

Have images fetched automatically, maybe have a special attribute on the img`element to tag them as important and only prefetch this images

Alternatives considered

No response

Importance

would make my life easier

Additional Information

I know that the problem arises because the navigation is done client side and the preload does fetch js/json. which includes the image urls but the browser won't start to fetch the until they become part of the html.


I started with svelte two weeks ago maybe I missed something

@eltigerchino eltigerchino added the feature request New feature or request label Oct 14, 2023
@thet0ast3r
Copy link

I also thought of something like that, but i think here are some valid considerations:

  • api data tends to be much, much smaller & should have more impact on the snappiness of a site than image data. As the time we have available to load data is rather short (on hover, onpointerdown) this gives great improvements in terms of perceived speed. Not so much with images, when the download of your image data, which would take 500ms is 'sped up' by 50ms that is only roughly 10% better performance.
  • how to deal with all the data? if a user hovers over multiple fields, you start to request mb's of resources, potentially clogging up the user's bandwidth to get the needed api stuff quickly. Do you abort all requests on mouse out(when the user decides not to click a link)?

I think your best bet is to load image previews/placeholders with js when loading page/component data, to 'instantly' show some preview and occupy the correct dimensions, and then just load the full-res image once the user navigated to the page.

@LorisSigrist
Copy link
Contributor

Starting the download of images that have fetchpriority="high" on them when preloading seems like a good idea. However, this should be non-blocking. If the navigation completes before the images is fully loaded, the site should be displayed anyways.

@thet0ast3r
Copy link

hmm. Starting the download of any images on user hover seems pretty disrespectful of a user's bandwidth. Onpointerdown, yeah, then the user most likely will navigate to that page, but not in all cases. Also, one would need to somehow know the size of the asset. imagine preloading 10mb of images, that's probably gonna hog your connection for some time. (I'm thinking about people on slow or unstable connections).
Also, how about the request limit on http 1.1? Requesting 6 unneeded images will stall everything else, or am i misinterpreting something here?

@LorisSigrist
Copy link
Contributor

I agree that overly optimistic image preloading could cause problems. That's why I specified that only images with fetchpriority="high" should be preloaded. That's an explicit opt-in by the developer that they want that image to be there as soon as possible, and preloading it would reflect that intention.

There are a few reasons that I don't believe preloading would cause network-congestion problems:

  1. Developers already know to only use fetchpriority="high" once, maybe twice per page.
  2. The main weakpoint of most connections isn't bandwidth, it's latency.
  3. No Browser actually obeys the 6 http connection limit. In practice you have >20.
  4. If the images are huge, the solution to the bandwidth problem isn't to delay loading as much as possible, it's compression & downscaling.

If bandwidth is a problem, then preloading is disrespectful to the users. Agreed! But if bandwidth isn't a problem, which in most places it's not, then not preloading is disrespectful to the users' time.

If developers are worried that their userbase is bandwidth limited they could simply not use fetchpriority="high", or just minimise the use of images all together. That's the exception not the rule.

We need to trust developers to do the right thing for their product & userbase. The best way to do that is to open as many doors as possible and letting them choose.

@thet0ast3r
Copy link

Still, while it would be possible, i am really not sure if it is even worth the hassle.

To address your reasons:

  1. Seems ok, im not disagreeing here.
  2. Well, if you live in the EU like me, there still are lots of connections via DSL that go down to 4mbit/s but still have decent ping (>50ms). While they slowly get replaced by 4g/5g and fiber/coax, i still think it is relevant to think about these users. Another point: Your server has a limited bandwidth, too.
  3. my latest google chrome obeys this limit (6 connections) when using http1.1 on a https website. Tested 2 minutes ago. All other requests are stalled in the meantime.
  4. True, here i was thinking a bit more 'general', i.e. 'assets'. Often pages have background videos, etc. I feel like if there is a built-in solution in sveltekit, it should be somewhat general.

I trust devs to do the right thing. But a framework often also acts as a sort of 'guideline': for example, sveltekit does not offer to use 'sveltekit-preload-data' eagerly, without hover, yet it supports it with code. Still the functions to preload data and code are pretty much identical (i am assuming this, didn't verify) so what's stopping them to make preload data and preload-code have the same functionalities?

For now i guess i'll resort to using tiny placeholders that i get in my loading function and inline them as base64. Because with sveltekit, images are only one roundtrip away from the preloaded data. As for me, i'd rather have 'instantaneous' placeholders on all my e.g. thumbnails, instead of eventually preloaded images on some of my content.

Nevertheless, i think it is a very interresting topic to discuss.

@rbozan
Copy link

rbozan commented Jan 19, 2024

Can't you somehow use html tag?

@alex-frx
Copy link
Author

Can't you somehow use html tag?

@rbozan I do not think this I possible. Because I want to start loading images from route b while im on route a.
The image element doesn't exist. And the things that smelt preload is javascript - which contains the image tags. but they are not inserted into the Dom so no preloading is done

@rbozan
Copy link

rbozan commented Jan 19, 2024

Can't you somehow use html tag?

@rbozan I do not think this I possible. Because I want to start loading images from route b while im on route a. The image element doesn't exist. And the things that smelt preload is javascript - which contains the image tags. but they are not inserted into the Dom so no preloading is done

I understand but if you have prefetchData function from sveltekit , apparently it also returns the data from your load function of that route. Can't you use that to then add the link rel="preload" HTML tag?

Apparently GitHub removed my tag or tried to render it.

@kissge
Copy link
Contributor

kissge commented Jan 24, 2024

A workaround I've come up with is to implement both +page.server.ts AND +page.ts for the soon-to-be-visited route.

/* +page.ts */

export function load({ data }) {
  if (typeof document !== 'undefined') {
    // Preload the header image
    new Image().src = data.headerImageURL;
  }

  return data;
}

@MentalGear
Copy link

I thought a while about this, and came up with the following optimized approach:

  1. Get your image data via the preloadData function.
  2. Preload the actual image object, by adding an img tag with the img url and srcset into the current page, but hidden.
  3. Iterate 2 for each image, keep a tracker when an image has finished loading and insert the next one, optionally allow n parallel preloads.

This guarantees:
a. that the native browser's algorithm is used to select the fitting srcset image.
b. let's the browser decides when it is best to download these extra images, as it might still have other images on the current page to finish that the user is waiting for.

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

No branches or pull requests

7 participants