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

Simple Stack Stream - Cannot navigate in Viewtransitions #66

Open
1 task
gitjoshu opened this issue May 10, 2024 · 6 comments
Open
1 task

Simple Stack Stream - Cannot navigate in Viewtransitions #66

gitjoshu opened this issue May 10, 2024 · 6 comments

Comments

@gitjoshu
Copy link

gitjoshu commented May 10, 2024

Astro Info

Astro                    v4.8.2
Node                     v20.12.2
System                   Linux (x64)
Package Manager          npm
Output                   server
Adapter                  @astrojs/vercel/serverless
Integrations             @astrojs/react
                         @astrojs/tailwind
                         simple-stream

If this issue only occurs in one browser, which browser is a problem?

Chrome

Describe the Bug

When I navigate with ViewTransitions doesnt work as I expected

What's the expected result?

I expect to navigate with view transitions and the simple-stack-stream

Link to Minimal Reproducible Example

http://localhost:4321/

Participation

  • I am willing to submit a pull request for this issue.
@bholmesdev
Copy link
Owner

Thanks for the issue @gitjoshu! Unfortunately, http://localhost:4321/ isn't super helpful for me to reproduce 😛 Is it possible to replicate in a stackblitz environment using one of our astro templates?

@gitjoshu gitjoshu changed the title Simple Stack Stream - Cannot read properties of undefined (reading 'headers') Simple Stack Stream - Cannot navigate in Viewtransitions May 14, 2024
@gitjoshu
Copy link
Author

Hahahah oh my god I thought I had sent you the complete description of the problem, I'm sorry you should for this meme @bholmesdev.

I take advantage of the fact that you told me to replicate it in the stackblitz environment to send it to you as well.

The stackblitz environment is as follows: https://stackblitz.com/edit/github-nr3pw4-2z5kwa?file=src%2Flayouts%2FLayout.astro,src%2Fpages%2Findex.astro,astro.config.mjs&file=src%2Fcomponents %2FCalendar.astro,src%2Fpages%2F[selectedYear]%2Findex.astro,src%2Fpages%2Findex.astro

There are two cases in which the behavior is not as expected:
1.- If you are on the home page and navigate to a calendar in the menu, I wait for the "Loading" to appear for 3 seconds and then load the page. What happens is that the screen remains locked and after 3 seconds the calendar page loads.

2.- If you are on the page of one of the two calendars (refresh page and wait calendar view), and then you navigate to the other calendar page, it remains set to "Loading".

It is not possible to use simple-stack-stream anyway and this behavior is normal.

Thanks in advance, I really appreciate what you do for the community, it's awesome

@bholmesdev
Copy link
Owner

@gitjoshu haha totally fine! appreciate that Stackblitz environment. I'll admit I've been putting these issue logs on the backburner between travel weeks and Astro's launch week, but know that I'm tracking this.

From reading your issue, I think this is because of Astro's view transition behavior. We use a client-side fetch call to navigate, which unfortunately waits for the entire stream to return instead of rendering the first chunk that streams in. Hence no loading state with a long hang time. This might be resolved using Chrome's new MPA view transitions proposal, which you can try out in canary before it goes stable next month.

To be honest, this sounds like an Astro core concern. I'll see what the platform team thinks. For now, check out that MPA proposal to see how it performs

@bholmesdev
Copy link
Owner

Update: we're now working on an official feature in Astro core to address simple-stack-stream's use case! We're calling this "server islands," and you can take part in the RFC conversation.

This model is quite a bit simpler than Suspense. Instead of streaming content, we request suspended components client-side with a fetch call. This should address your view transitions issue since we no longer rely on streaming to fill loading states. If you want to try an early preview (that only works in the dev server!), you can follow these installation instructions.

I'm very curious how server islands can fill the same use cases as suspense. Let me know if you try it @gitjoshu!

@gitjoshu
Copy link
Author

gitjoshu commented Jul 25, 2024

Hello again @bholmesdev, how are you?!

Sorry for taking so long to respond, but I was on vacation and busy with other projects. I was aware of the news and couldn't wait to try it out and today I was able to try it out and the results are incredible.
I only had one problem and that is that I tried a component that has a script which is executed before being in the html and the script depends on the DOM elements of this. Example:

<FullYearCalendar server:defer>
<FullYearCalendarSkeleton slot="fallback" />
</FullYearCalendar>

FullYearCalendar component:

<div>
<calendar id="calendar"></calendar>
</div>
<script>
const calendar = document.querySelector("#calendar")
console.log(calendar)
</script>

calendar is undefined. To fix it for the moment I added a mutation observer as follows to add a customEvent:

export function initDOMObserver(targetId: string, eventName: string) { 
const observer = new MutationObserver((mutationsList) => { 
for (let mutation of mutationsList) { if (mutation.type === "childList") { 
mutation.addedNodes.forEach((node) => { 
if (node.nodeType === 1 && (no from as HTMLElement).id === targetId) { const event = new CustomEvent(eventName, { detail: { id: (node ​​as HTMLElement).id }, });
 observer.observe(document.body, { childList: true, subtree: true });
}

and apply it like this:

<div>
<calendar id="calendar"></calendar>
</div>
<script>
import { initDOMObserver } from "@/utils/helpers";

initDOMObserver("calendar", "calendarAdded");

document.addEventListener("calendarAdded", function () {
const calendar = document.querySelector("#calendar")
console.log(calendar)
});
</script>

I don't know if there is another way to solve it or if it will be worked on.

I love server-islands !!!

image
image

@bholmesdev
Copy link
Owner

@gitjoshu Ah ha, that's a good catch. I'm actually building a library to address exactly this 😅

I understand that Astro will bundle scripts ahead of fetching the HTML. A mutation observer is one solution, but I've found web components to be a bit simpler. These give you a lifecycle function (connectedCallback) to run a script once a particular HTML element mounts. Here's how that calendar example might work:

<calendar-container>
<calendar id="calendar"></calendar>
</calendar-container>

<script>
class CalendarElement extends HTMLElement {
  connectedCallback() {
    const calendar = document.querySelector("#calendar")
    console.log(calendar)
  }
}
customElements.define('calendar-container, CalendarElement);
</script>

The library I'm working on could simplify the above even further by making a unique web component for you:

<RootElement>
<calendar id="calendar"></calendar>
</RootElement>

<script>
RootElement.ready(() => {
  const calendar = document.querySelector("#calendar")
  console.log(calendar)
});
</script>

I'll be sharing more on that from https://simple-stack.dev/query !

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

No branches or pull requests

2 participants