Skip to content

Conversation

@paoloricciuti
Copy link
Member

Closes #14711

This all sprouted from the fact that using onNavigate to trigger view transitions doesn't work if the receiving component uses await. The issue is that the DOM is not mounted yet when the complete promise resolves because it's still awaiting.

But when trying to fix this bug, I realized that this was probably messing with focus management and scroll restoration because we were awaiting tick instead of settled. This changes that (using the namespaced import so that it also works for Svelte 4/Svelte 5 before settled versions).

There doesn't seem to be an app that uses async: true in tests so I'm not sure how to test this (we should probably add one). Let me know if I should add one ☺️


Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with pnpm test and lint the project with pnpm lint and pnpm check

Changesets

  • If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpm changeset and following the prompts. Changesets that add features should be minor and those that fix bugs should be patch. Please prefix changeset messages with feat:, fix:, or chore:.

Edits

  • Please ensure that 'Allow edits from maintainers' is checked. PRs without this option may be closed.

@changeset-bot
Copy link

changeset-bot bot commented Oct 24, 2025

🦋 Changeset detected

Latest commit: 91ee377

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sveltejs/kit Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@sillvva
Copy link
Contributor

sillvva commented Oct 24, 2025

In my app, I resorted to using an await wait(100), which "worked".

After seeing this PR, I tried importing settled from svelte, but it didn't work. The page-to-page transitions stopped working again. Or maybe it just doesn't work that way? I'm not sure.~

Edit:
Nevermind. I tried installing this PR directly and it seems to work! Awesome!

@paoloricciuti
Copy link
Member Author

Yeah, just awaiting settled in onNavigate doesn't work because it's too early, and it needs to also have the latest version of svelte...if you want to do it in user land with an old version of svelte and SvelteKit you can do this

let resolver: (() => void) | null = null;

$effect.pre(() => {
    void page.url;
    resolver?.();
    resolver = null;
});

onNavigate(({ complete }) => {
    const promise = new Promise<void>((res) => {
        resolver = res;
    });
    return new Promise((res) => {
        document.startViewTransition(async () => {
            res();
            await complete;
            await promise;
        });
    });
});

Which is better than awaiting a random 100ms (which will also break if the promise in the new page take longer than that).

@paoloricciuti paoloricciuti merged commit 1f6fb19 into main Oct 25, 2025
38 of 39 checks passed
@paoloricciuti paoloricciuti deleted the settled-instead-of-tick branch October 25, 2025 15:03
@github-actions github-actions bot mentioned this pull request Oct 25, 2025
@sigerello
Copy link

I've tried to use the build from this PR directly and it worked great, but now after updating to v2.48.0, the issue appears again – afterNavigate callback is triggered right away, not waiting for remote function to resolve. It appears #14793 breaks it.

@paoloricciuti
Copy link
Member Author

Mmm I see onNavigate working correctly on my side...will try to check later

@paoloricciuti
Copy link
Member Author

You are right could be on the svelte side tho 🤔

await tick();
// svelte.settled is only available in Svelte 5
if (/** @type {any} */ (svelte).settled) {
promises.push(/** @type {any} */ (svelte).settled());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can svelte.settled() take a long time? After upgrading to v.2.48.0 we suddenly start seeing full-page navigation where we previously saw client-side navigation. It seems like the e.preventDefault() for links is not triggered, so we often end up getting the native full-page navigation instead of sveltekit's client-side navigation.

If i go into our app and wait a little bit, then client-side navigation usually works. But if i go into our app and click on a link within <5-10s of initial load then a full page navigation is triggered.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, i don't know if we're using svelte.settled - where is this defined?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you also upgrade svelte to the latest version?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, we have a different issue with the latest Svelte versions (since 5.41.1, 5.41.0 is the latest working version for us). We're heavily affected by this performance regression: sveltejs/svelte#16990

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the problem, unfortunately...previous svelte versions don't resolve settled 😔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, okay. We're kinda in a deadlock now, we can't upgrade Svelte or Sveltekit with the latest updates :/ With all of these being minor updates it feels kinda scary that there are regressions in performance and behaviour.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @MathiasWP the full-page navigations don't sound normal. Hydration shouldn't be taking that long. Is it possible for you to reproduce this and create an issue for it?

Copy link
Contributor

@MathiasWP MathiasWP Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it was because we used version 5.41.0 of Svelte together with the latest version of SvelteKit that had this PR merged. The bug disappeared in sveltekit after updating svelte with the fix in #17051.

It would be nice in the future to get a heads up if a sveltekit update requires a minimum version of Svelte, this wasn't really communicated anywhere :/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't intentional. We're trying our best

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The minimum version of Svelte should always be the one specified in the peerDependency list of SvelteKit's package.json file. I think the package manager will tell you if it's not within the specified version range.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

view transition completes before components mounted with experimental async enabled

7 participants