That is an ambitious title for an article. An ambitious goal in general. Hydration, the process of spreading JavaScript interactivity back into our...
For further actions, you may consider blocking this person and/or reporting abuse
Very nice innovations!
Is Marko built on top of Qwik?
Or are they 2 completely separate frameworks with similar ideas?
Two completely separate projects with similar ideas.
Marko was created and open sourced at eBay in 2014 and powers ebay.com. It has been pioneering the load performance optimized JavaScript space leveraging smart compilation for most of the last decade. Marko was the first open source JS framework to support automatic Partial Hydration(Islands) and Out of Order Streaming and has continued to innovate this space since then.
Qwik is the result of observations Misko Hevery made while working on Angular. He'd formalized it and presented the ideas back at a conference in 2019, but realized that Angular wasn't going to be able to support this vision. He left Google in 2021 and joined Builder.io to develop this new framework.
Great article, Ryan, thanks, and which prompted me to pause and ask again a very fundamental question as to which framework to use for a biz startup web app now about to approach Minimum Viable Product development. My question to you is, if you were to decide which technology/framework to use, which one would it be -- Sveltekit, Qwick/Partytown, Marko, Astro -- given the following context/specs:
If it's Marko, great! But if Marko can't meet all the above requirements, which framework would you choose if this is your project?
Would love to get your take on this.
I would add:
😛
So... What did you choose?
I learned a lot about SSR and hydration from your articles and videos. Thanks a lot.
what resources( article, video, source code) would you recommend for learning the implementation detail about hydration? like from scratch.
Quite interesting as usual. And a very deep subject indeed. Still trying to wrap my head around these "new" concepts. For example, could we say that resumability is like using something like petite-vue with a server side framework like say Express where petite-vue resumes what has been rendered on the server? Just thinking outload.
Most of these frameworks that add arbitrary bits of JS on top of HTML still need to "render" once to setup their reactive subscriptions as they are determined at runtime. Qwik actually does determine them at runtime but with the server acting as the one time it runs, and then serializes the subscriptions into the page. Marko uses compiler analysis to know the dependencies and serializes that.
But most of the motivation here is to provide a single app experience when authoring. Ultimately what happens is we let the user basically write a full JavaScript application. Picture like writing a React app. And then through build process we break it into the little pieces that need to be sent to the browser, and serialize enough data so barely anything actually runs on page load. From there using fine-grained reactivity (like what petite-vue or Solid has) we just update the parts that change, as needed on end user interaction.
There's an assumption with the concept of resumability (and from what I read in this article) that perhaps I fail to understand. The assumption is that the app's code is nicely separated into components, and that each component's code is responsible for handling the events etc.
From my experience with larger apps, most of the code is actually a bunch of utils, common hooks, business logic, code that is not cleanly divisible to components.
In code bases like that, wouldn't it be so that resuming the app when the event happens leads to a big download and execution of those common dependencies? Wouldn't it be so that unless you really carefully craft your app to be separated to components and clean dependencies, what you did with resumability is postpone the long download and INP to after the first interaction that requires all those dependencies, perhaps separating out some component code at the fringe?
Maybe Marko/Qwik came up with solutions for this, would love to hear!
Their are a couple pieces here. Most of these solutions were born out places where heavy business logic was preferred on the server anyway. Generally right now we are seeing this applied to MPAs which means that a lot of the heavy lifting is server side. We aren't necessarily talking admin dashboards, but eCommerce sites and like Google search.
I also don't tend to combine the download portion with the resumability. Qwik often does talk about that, but I think that distracts. Marko actually doesn't have that fine grained lazy loading mechanism. We're still of the mind that that sort of loading is still best served in larger parts related to defined/known feature sets and evaluating and making decisions rather than just breaking everything apart. So I wouldn't focus on that.
The important part is not hydrating when the page load. You can load all the JavaScript upfront, it isn't going to execute at that time anyway. Obviously some stuff being lazy is valuable but we don't have to necessarily wait until someone clicks.
The key to resumability is that the first interaction is the same without running a bunch of code as it would have been if you did all that hydration work. You aren't deferring work as much as eliminating a stage. It's a bit like trading CPU for memory. We serialize more to run less.
But back to the beginning if all the logic is needed in the browser then yeah there isn't much for that. We've seen in practice with Marko we can eliminate more unnecessary code than you'd expect making even fully interactive demos smaller than their typical client counterparts but the tradeoff isn't in INP or interactivity but rather server rendering time and network bandwidth. However using knowledge of what can or can't change actually counters that.
If part of the page never needs to update it isn't just the JavaScript you can save on but the related serialized data, both internals needed for Resumability, and end user data stores they would have otherwise needed to be present to properly hydrate. We get to just skip on all of that.
Of course with anything mileage will vary. If a system's business logic is one big tightly couple unit then maybe you are in for a bit of a hit anyway. But even in that case there is still a lot of opportunity here to reduce code and improve page startup.
Thanks, I think I understand the premise better.
In a nutshell, seems like resumability doesn't solve the issue of hydration as a web-development problem (e.g. how web-component code attach to custom HTML elements in the markup), but rather the hydration problem as presented by frameworks, because they have to generate all this internal data (e.g. VDOM in React). This is of course a valuable thing to solve.
Yeah. More or less. Keep in mind most people author webcomponents with frameworks (like Lit or Stencil) so it is more of the same here too. But fundamentally this is a cost due to how we model the UI declaratively and need to get back to that when the app wakes up.
I guess this is where event delegation comes in, just imagine downloading 100+ listeners to over a 100 list items. And do event listeners get downloaded every time?
Event delegation is the key to not running over the component tree on client side startup. It still additionally requires being able to hoist out all the event handlers in a way they can be registered top level without running any component code which can be complicated since these tend to close over state.
It also requires writing some unique identifier/scope information into the DOM elements themselves at SSR time to know where to find the code and serialized state.
But if you can compile it that way ahead of time, when the browser starts up we only have to add a global delegated event handler for each type of event. No need to run the components. It's only when someone triggers the event that we'd look at the event target and walk up finding the appropriate handlers and scope based on what was written into the HTML that we execute application code.
All those complications is the result of applying SPA frameworks to what they are not applicable.
Just create traditional multi page applications, use Web Components for encapsulation and reuse and be happy.
If only it were that simple across the board. The frameworks highlighted in this article aren't actually SPA frameworks. And using frameworks at all is overkill for certain things.
Server rendering + hydrating Web Components is its own thing. Lit has been adding support for this but more of the same, trading one framework for another. It does serve as a good basis for Island architecture similar to Astro. But as you scale for certain types web applications hydration comes back to haunt you.
While complex what is cool about the approach discussed here is it does reduce the startup execution cost. Yes writing pure vanilla can do this as well, but then SSR gets trickier as relying on emulated DOM on the server is recipe for poor performance.