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

Try to fix SPA initial behavior for 404s #4116

Merged

Conversation

PH4NTOMiki
Copy link
Contributor

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 pnpx changeset and following the prompts. All changesets should be patch until SvelteKit 1.0

One of the ways to fix #4049 (comment)
we can probably completely discard that initialization boolean in router if we decide to do this.

@changeset-bot
Copy link

changeset-bot bot commented Feb 24, 2022

🦋 Changeset detected

Latest commit: 77d5b96

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

@PH4NTOMiki
Copy link
Contributor Author

@Rich-Harris @benmccann what do you think of this, am I missing something?

@benmccann
Copy link
Member

benmccann commented Feb 24, 2022

I have some ideas about how this code could be cleaned up. I'll try to share something more shortly

@PH4NTOMiki
Copy link
Contributor Author

Okay, fully understand, just one of ideas, definitely not the best one.

@@ -294,7 +295,7 @@ export class Router {
routes: this.routes.filter(([pattern]) => pattern.test(path)),
url,
path,
initial: !this.initialized
initial: skip_browser_reload ?? !this.initialized
Copy link
Member

Choose a reason for hiding this comment

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

I haven't gotten to sit down and understand this PR yet, but I'm concerned that this variable no longer represents the initial page load, but is still being called initial. I think we'd need a better way to represent this

I sent a PR before this one to cleanup the router APIs and moved this flag to Renderer.has_hydrated: #4101

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that makes sense

@benmccann
Copy link
Member

It was unclear to me what this is supposed to be fixing, but it looks like it's referred to in the comments of another PR (#4049 (comment)). A closed PR is a hard place to have a discussion about this. Can you open a new issue for it?

@Rich-Harris
Copy link
Member

Thanks. I've added a test that fails without this PR.

Been thinking a little more about the circumstances in which this issue arises. We basically only need the guard when a) we're hydrating a page from a fallback 200.html (or equivalent) page, or b) we've invalidated a URL or the session and we haven't yet navigated away from the initial page. The current check is a little too broad. Will push up some changes shortly

@@ -449,6 +450,10 @@ export class Router {
}

if (details) {
if (this.is_fallback && info.url.pathname !== location.pathname) {
Copy link
Member

Choose a reason for hiding this comment

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

what is the second half of this check doing? I don't understand how an app can be initialized as a fallback/SPA and then later not become one. Maybe this variable is representing something else in this case as should have a different name?

Copy link
Member

Choose a reason for hiding this comment

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

an SPA can have some pages prerendered. the bug we're trying to avoid is infinite reloads when the initial hydration fails (or subsequent invalidations that aren't caused by navigation), rather than preventing full page reloads across the board

@@ -448,6 +450,10 @@ export class Router {
}

if (details) {
if (this.is_fallback && info.url.pathname !== location.pathname) {
Copy link
Member

Choose a reason for hiding this comment

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

we should probably add a comment to clarify at least

Suggested change
if (this.is_fallback && info.url.pathname !== location.pathname) {
// if navigating to a prerendered page
if (this.is_fallback && info.url.pathname !== location.pathname) {

but another way to write this might be to move the URL check to renderer. overwriting is_fallback seems a bit funny to me because at this point it is still a fallback. it's not until after we've left and navigated to the new page that it's not a fallback

Copy link
Member

Choose a reason for hiding this comment

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

Not sure I understand what you mean about moving the URL check to renderer. The responsibility for this stuff (to the extent that the two things are separate — I'm going to open a PR today to merge them, because it really will simplify things) lies with the router

it's not until after we've left and navigated to the new page that it's not a fallback

pushing state is navigating to the new page

Copy link
Member

Choose a reason for hiding this comment

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

I mean you could change if (!navigation_result && this.router?.is_fallback) { to if (!navigation_result && this.router?.is_fallback && info.url.pathname !== location.pathname) {

If I understand correctly, when this is triggered we will do a server-side nav. This page is still a fallback page in my mind until the server-side nav has happened

Copy link
Member

Choose a reason for hiding this comment

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

Actually you know what? If we were to compare url.pathname with location.pathname at that point, it would arguably be simpler to do away with the fallback/non-fallback distinction altogether and just always bail out of full page reloads if they're the same (i.e. it's not a navigation, it's a hydration/invalidation). commit inbound

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's simpler and should work.

@Rich-Harris Rich-Harris merged commit 2e4a44f into sveltejs:master Mar 1, 2022
@github-actions github-actions bot mentioned this pull request Mar 1, 2022
@PH4NTOMiki PH4NTOMiki deleted the fix-spa-error-with-initialization branch March 1, 2022 16:17
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.

None yet

3 participants