RafidMuhymin / astro-spa

An Astro JS component that turns a website into an SPA and boost performance using various techniques
MIT License
391 stars 14 forks source link

Client-side components not being rehydrated #3

Open vxncetxn opened 2 years ago

vxncetxn commented 2 years ago

Describe the bug Client-side components are not rehydrated in the case where I navigate from Page A to Page B, then back to Page A. This means that any client-side components that previously worked on Page A when I first loaded it will cease to work when I return to it.

My understanding is that this is because the hydration scripts outputted by Astro are ES modules, and ES modules can only be evaluated once per page load. This means that the hydration scripts for Page A ran once to hydrate any client-side components (so it works initially), but on return to the page, since the page is not actually reloaded, the script will not run again (and therefore any client-side components will not be rehydrated) despite any attempts at re-injecting it to the head. Refer to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#other_differences_between_modules_and_standard_scripts

EDIT: Just to elaborate a little, the core issue at hand here is not about the exact navigation sequence of Page A -> Page B -> Page A, but the fact that once a page has been visited, returning to it will lead to any client-side components no longer working. You can play around with the back/forward button and see that once any of the pages have been visited, any return to it will yield the same problem.

To Reproduce Steps to reproduce the behavior:

  1. Go to https://test-astro-spa.vercel.app/
  2. Verify that Counter works in Index page.
  3. Click on "Next" link to go to /Next page.
  4. Click on "Back" link to return to Index page.
  5. Verify that Counter no longer works as it should.

Configuration for astro-spa <Spa containerSelector="#container" />

Versions

RafidMuhymin commented 2 years ago

Thanks, @vxncetxn for reporting the issue. I'll take a look as soon as possible.

jtag05 commented 2 years ago

This seems to still be an issue and primarily related to using containerSelector. I'd be interested in helping to resolve this if possible.

jtag05 commented 2 years ago

Seems that the issue, in my case, was related to disabling scrollIntoView. Changing https://github.com/RafidMuhymin/astro-spa/blob/main/buildPage.js#L12-L19

? `const newContent = doc.querySelector("${containerSelector}");
        ${
          scrollIntoView
            ? `const container = document.querySelector("${containerSelector}");
        container.replaceWith(newContent);
        newContent.scrollIntoView(${JSON.stringify(scrollIntoViewOptions)});`
            : ""
        }

to

? `const newContent = doc.querySelector("${containerSelector}");
        const container = document.querySelector("${containerSelector}");
        container.replaceWith(newContent);
        ${
          scrollIntoView
            ? `
        newContent.scrollIntoView(${JSON.stringify(scrollIntoViewOptions)});`
            : ''
        }

would resolve the issue. It seems that the new content is not being replaced when scrollIntoView is false.

jtag05 commented 2 years ago

I opened PR #6 which resolves my issue, which turns out to be the same issue as #5