-
Notifications
You must be signed in to change notification settings - Fork 0
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
Flexible Hydration with Multi-Framework Islands on Vike #1
Comments
It's been fascinating to explore this! Although there aren't many online resources about islands, I've found inspiration from Jason Miller's blog post (https://jasonformat.com/islands-architecture/), the documentation provided by Astro, and others. To clarify my goals, I aim to avoid shipping JavaScript responsible for rebuilding the entire application/website state merely to hydrate a basic isolated widget without appealing to an imperative approach. Instead, I seek a declarative approach — one that enables selective and scheduled hydration, particularly focusing on strategies related to viewport visibility and media query matches — to significantly enhance TTI speed. Additionally, my preference leans toward creating islands (components) within another component using directives, providing greater control. Initially, I had imagined something multi-view at the page level, like you showed. However, it might not offer ease of hydration management inside the components. Consider, for instance, hydrating a navbar menu solely on mobile devices... It's noteworthy that islands can be marked at the component level, not necessarily confined to the page level, as seen in Astro's usage of client directives on . My current idea revolves around marking a Vue island within a JSX component, adjacent to a React island, inspired by your example but without replacing //+Page.tsx
import RClock from "~/components/Clock.tsx"; // React Component
import VCounter from "~/components/VCounter.vue"; // Vue Component
import { withIsland } from "island-framework";
const Clock = withIsland(RClock);
const Counter = withIsland(VCounter);
export default function Page() {
return (
<>
<button>Static button not hydrated</button>
{/* Hydrate React component on viewport visibility */}
<Clock client:visible />
{/* Hydrate Vue component only on mobile */}
<Counter client:media="(max-width: 576px)" />
</>
);
}
Once again, thanks for sharing your insights. |
Super interesting, thanks for sharing.
What you show in your
It sounds like you want to do way more than just Server Components. Server Components would be basically islands which are statically marked as never to be hydrated. And even this is quite a complex topic already. So if you manage to pull off something that works and has a nice DX, we (Vike) would be very interested in it (FYI @brillout) |
That's exactly what I'm doing! Basically, HOC Finally, it seems to be functioning now, making significant progress in the Proof of Concept (PoC)! Feel free to explore the source code for further insights. Notably, we've achieved the ability to import Vue components within server-rendered React components, and vice versa. Moreover, we can control hydration using the directives. <script setup async lang="ts">
//./pages/vue/+Page.vue
import { island } from "~/island/vue";
import RClock from "~/components/Clock.react";
const Clock = island(RClock);
</script>
<template>
<Clock client:visible />
</template> // pages/index/+Page.tsx
import VGreenCounter from "~/components/VGreenCounter.vue";
import { withIsland } from "~/island/react";
const GreenCounter = withIsland(VGreenCounter);
export default () => {
return (
<div>
<h2>Vue Hydrated on Scroll</h2>
<GreenCounter count={1} client:visible />
</div>
);
}; However, there's always room for enhancement. This setup can benefit from better type support, optimizations for performance, thorough testing, and potential refactoring for improved efficiency. What do you think? |
Wow yes, just saw your latest pushes. This is becoming exciting :) I'll have a deeper look in the next couple of days and get back to you. Thank you so much for doing that! |
@luisfloat This is very impressive!
Feel free to say no to any of these if you don't have time 🙏 |
Thanks, @AurelienLourot! I've just renamed the repo to "vike-island-example". I'm planning to refactor the code by the end of the week, enhancing integrations, refining types, and addressing dev-mode warnings. After the refactor, I'll proceed with creating the PR you suggested, describing islands and linking to relevant resources alongside my example. Moreover, I anticipate gaining new insights to enhance the DX through this refactor. Creating a package for simplified implementation is something I'll strongly consider. |
Hey, @AurelienLourot. I've completed the intended refactor along with incorporating some new significant features. Here's a breakdown of the updates:
Next, I'll start the Vike docs PR as per your suggestion. I believe it might be a good time to close this issue (though anyone is welcome to create new issues). What do you think? |
Really nice, sounds great, thanks a lot 🙏 |
Thanks @luisfloat for exploring this. Interestingly I had a different understanding of what islands are, especially because one island could be in React, another one could be in Vue, etc. At least this is an idea that caught my eye in https://docs.astro.build/en/concepts/islands/ . So here is the direction I would have taken:
1. Replace
+Page.tsx
by one+
file per islandI would create one new setting per island, say
islandReact
andislandVue
, so for each page I would have files like+islandReact.tsx
and+islandVue.vue
instead of+Page.tsx
.See https://vike.dev/meta for creating your own settings.
Page
is just a setting.2. Adapt
onRenderHtml()
andonRenderClient()
for rendering both islandsIt would look like
I basically merged these two examples:
What do you think? One drawback of this is that the amount of islands is hardcoded for all pages of the entire app, as is their layout. But I'm wondering if it is any different with Astro if you want to mix React and Vue? 👀 Anyway such an example of mixing React and Vue in the same page on Vike could be quite nice.
But if what you want is just to have certain areas of the app not being hydrated, you are basically reinventing Server Components? That's quite a complex topic and we have it on our radar: https://vike.dev/react#react-server-components
The text was updated successfully, but these errors were encountered: