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

Make data-sveltekit-prefetch work with mousedown #7289

Closed
superboss224 opened this issue Oct 17, 2022 · 10 comments · Fixed by #7776
Closed

Make data-sveltekit-prefetch work with mousedown #7289

superboss224 opened this issue Oct 17, 2022 · 10 comments · Fixed by #7776
Labels
Milestone

Comments

@superboss224
Copy link

Describe the problem

At this time, data-sveltekit-prefetch works with mouseover on PC, while this behavior lets the browser prefetch a link sooner, it can lead to two issues :

  • prefetching more links than necessary when an user just hovers over big links without clicking on them, which can lead to additional useless requests, which are counted when using edge hostings like Cloudflare Workers or Deno, and which can lead to more data consumption
  • prefetching too soon, on a near-realtime application, fetching 500ms too soon can lead to outdated data (for example, if it's realtime stats app or a chat)

Describe the proposed solution

prefetching on mousedown still lets 100ms (duration of a click) to prefetch a page before the user's click ends, and if a website is hosted on a nearby server, or on the edge, the user will keep a feeling of immediacy, it will also do requests only when the user really wants to navigate to the page

To implement mousedown prefectch, we could have something like that for per-link or per-parent-element configuration:

<a href="/mypage" data-sveltekit-prefetch="mousedown"></a>

Or have a parameter like this in svelte.config.js :

prefetching: 'mousedown'

Alternatives considered

The alternative would be to prefetch programmatically with a custom directive, but it would require to reimplement a huge part of the prefetching syntax that sveltekit already provides, so I believe just having a way to opt-in mousedown prefetching would be a much better and cleaner way of using it

Importance

i cannot use SvelteKit without it

Additional Information

Prefetching on mobile already works on touchdown and does not need to offer another prefetch behavior

@gterras
Copy link

gterras commented Oct 17, 2022

While this idea is interesting the two issues you mention would still exist with mousedown prefetch hence I don't really understand the i cannot use SvelteKit without itpart since it seems you would be better off disabling prefetch completely.

@Conduitry
Copy link
Member

I don't think we need to support this in the framework. You can disable the built-in prefetching and then programmatically call https://kit.svelte.dev/docs/modules#$app-navigation-prefetch triggered by whatever you want.

@superboss224
Copy link
Author

superboss224 commented Oct 17, 2022

While this idea is interesting the two issues you mention would still exist with mousedown prefetch hence I don't really understand the i cannot use SvelteKit without itpart since it seems you would be better off disabling prefetch completely.

No, disabling prefetch completely causes visible lag to the user, which prevents me from making a truly smooth app for my users.

100ms is noticeable, meanwhile, having prefetch on mousedown makes the lag disappear.

I don't think we need to support this in the framework. You can disable the built-in prefetching and then programmatically call https://kit.svelte.dev/docs/modules#$app-navigation-prefetch triggered by whatever you want.

Yes but then it makes it more boilerplatey to implement it on my own programmatically, as I described in the issue

And the feature is here to be used, I just believe it can be best used with mousedown, so modifying the behavior or at least having the option would be great

@gterras
Copy link

gterras commented Oct 17, 2022

No, disabling prefetch completely causes visible lag to the user

So either the router introduces latency (which I have never noticed) then it's a specific issue or this actually concerns the entire web as it is structured, not really SvelteKit.

truly smooth app

If by smooth you mean instantaneous and your app isn't deployed in a restricted environment there are about 1001 factors that you have no control on that would make your app not "smooth".

it makes it more boilerplatey

This should be a less-than-10-lines helpers though!

@superboss224
Copy link
Author

So either the router introduces latency (which I have never noticed) then it's a specific issue or this actually concerns the entire web as it is structured, not really SvelteKit.

Prefetching routes also prefetches route's load() function, which makes queries to a database or at least makes a request which can take 100-200 ms, and that requests concerns the entire web, but prefetching that request eliminates this lag

If by smooth you mean instantaneous and your app isn't deployed in a restricted environment there are about 1001 factors that you have no control on that would make your app not "smooth".

Yes but the key to make a good app is to reduces that number of factors as much as possible, even if you can't eliminate lag for every people, eliminating it for good connections is already a huge achievement that I want to have on my app

This should be a less-than-10-lines helpers though!

Not if I have to add a Svelte Action on every link to make the helper work

@elliott-with-the-longest-name-on-github
Copy link
Contributor

Another vote for not implementing this at the Kit level. This is a super-niche use case, and if you're building an app where a hundred milliseconds of prefetch delay will result in stale data, you probably need to build some better method of invalidating stale data.

@superboss224
Copy link
Author

Another vote for not implementing this at the Kit level. This is a super-niche use case, and if you're building an app where a hundred milliseconds of prefetch delay will result in stale data, you probably need to build some better method of invalidating stale data.

The main reason is not to invalidate stale data, but to make less useless requests on edge workers, and/or to have less requests made when some user hovers over links in my website/app

Implementing it at the kit level just requires an option that replaces mouseover by mousedown when true, I don't believe it will bloat sveltekit nor make it more complex to do it, and it will provide the best way to prefetch data without fetching too much data

Maybe there's something I'm not realizing but I don't understand why it would be a bad thing for Svelte to provide the option, given how easily it can be implemented

For instance, Discord has mousedown prefetching aswell when clicking on a server, and I believe SvelteKit should be able to make ambitious apps of this level natively, unless there is a very good reason to not let SvelteKit get the feature, but for now, I don't see any

@gterras
Copy link

gterras commented Oct 24, 2022

make less useless requests on edge workers

This is a fair point, prefetch as it is now lacks a bit of subtlety in regards of limited resource, especially since sveltekit actively promotes serverless.

@dummdidumm
Copy link
Member

Two alternatives instead of making this configurable

Option 1: expose the lower-level APIs to determine the URL and if it should be prefetched (not external or reload attribute present on it), so people can implement their own ways.

Made-up example code:

import { browser } from '$app/environment';
import { findAnchor, prefetch } from '$app/navigation';

if (browser) {
  document.addEventListener('mousedown', evt => {
    const { url, external, reload } = findAnchor(evt);
    if (!external && !reload) {
      prefetch(url);
   }
  });
}

Option 2: Currently we trigger a custom event sveltekit:trigger_prefetch (THIS IS PRIVATE API DON'T USE) which only triggers actual prefetching if it finds a data-sveltekit-prefetch attribute. We could create a public blessed custom event which triggers prefetching without checking for the data-sveltekit-prefetch attribute but leaving all other logic in place.

@Rich-Harris Rich-Harris added this to the 1.0 milestone Nov 18, 2022
@ivanhofer
Copy link
Contributor

ivanhofer commented Nov 22, 2022

What about an option to disable prefetch further down the component tree?
So you can set data-sveltekit-prefetch globally and then disable it for a specific part of your application:

<body data-sveltekit-prefetch>
	<main> <!-- main content --> </main>
	<nav>
		<a href="/">Home</a>
		<a data-sveltekit-prefetch={false} href="/settings">User Settings</a>
	</nav>
</body>

I have a similar use case where preloading the route on hover could lead to some issues, But I don't want to disable prefetch for the rest of the application. Beeing able to opt-out at certain parts of the application would be a great addition.

Or also a +layout.js or +page.js option to prevent prefetching for certain routes would be an option, but I would imagine this beeing more complex to implement.

routes/settings/+layout.js

export const prerender = false

edit: I just saw that the prerender option exists already, but I guess this only applies when building the application and not when calling prerender during runtime.

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

Successfully merging a pull request may close this issue.

8 participants