question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Re-purpose / reuse root for SSR hydration / prerendering.

See original GitHub issue

Our current hydration implementation is broken! We are simply avoiding the duplication of your SSR nodes, but we are still patching everything from scratch. 😆

We could improve it this way:

function hydrate(element, map) {
  return element
    ? {
        tag: element.tagName.toLowerCase(),
        data: {},
        children: map.call(element.childNodes, function(element) {
          return element.nodeType === 3
            ? element.nodeValue
            : hydrate(element, map)
        })
      }
    : element
}

Unfortunately, this still does not take into account empty text nodes, which if not trimmed, would yield a tree that is not consistent with the new tree returned by the view, causing patch to do more work than it needs if we were hydrating correctly.

A more complex solution could be explored, but then how much is enough and can this be moved outside core?

I’ve been thinking about this today and considered many alternatives, and here is my proposal.


Re-purpose root for SSR-use for what-would-be the old element during the initial render.

I originally chose the name root because it was short and simple, but now I think that root should describe your application’s top element: <main>, <div>, etc., and NOT the HTML element to act as a container / host of your application tree (which is what we do now).

How will this affect existing apps?

Apps not using root.

Everything will continue to work as usual. 🎉

Apps using root.

Say you have this HTML:

<body>
  <div id="app"></div>
</body>

and used root like this:

app({
  view: () => <h1>Hello.</h1>,
  root: document.getElementById("main")
})

Now your app will render overwriting / obliterating <div id="app">, so the final HTML will look like this:

<body>
  <h1>Hello.</h1>
</body>

This is similar to how React behaves.

SSR

Using root for SSR pages would allow us to remove this part from core.

element = document.querySelector("[data-ssr]")

And use instead:

app({
  ...,
  root: document.querySelector("[data-ssr]")
})

Or a different data attribute; it’s up to you.

Finally, the old node for the initial render. Instead of introducing a new property, I propose using the load event, currently unused.

app({
  events: {
    load(state, actions, root) {
      return myOwnHydrationFormula(root)
    }
  }
})

so we can assign that result value to the node inside core like this:

node = emit("load", root)

Using a mixin for that would work as well. Obviously, we’d call that mixin Hydrator!

app({
  mixins: [Hydrator]
})

SSR Example

A full SSR page example would work like this:

<html>

<head>
  <script defer src="bundle.js"></script>
</head>

<body>
  <main data-hyperapp-ssr>
    <h1>My app.</h1>
  </main>
</body>

</html>
app({
  view: () => 
     <main>
        <h1>My app.</h1>
     </main>,
  mixins: [Hydrator],
  root: document.querySelector("[data-hyperapp-ssr]"),
})

/cc @andyrj @ngryman @SkaterDad @lukejacksonn @zaceno

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:28 (27 by maintainers)

github_iconTop GitHub Comments

4reactions
SkaterDadcommented, Jul 31, 2017

👍

I’m in favor of this idea. Replacing the root node makes more sense, and it’s one less useless <div> wrapper around an app. Also good that we can now specify what attributes/id to target.

However you decide to move the hydration out of core, that’s probably for the best also. No reason to ship code in core that 75% of your users won’t be needing (number pull out of thin air).

3reactions
jorgebucarancommented, Jul 31, 2017

By the way, I want to clarify that I do plan to use SSR in apps that require SSR, e.g., systems that want to adopt hyperapp, but are already largely SSR-based like a rails app.

But I don’t see why we should include it in core when we could use a mixin just as well.

P.S: Obviously this.

473f6926-779a-11e5-b88a-12771640ddce

Read more comments on GitHub >

github_iconTop Results From Across the Web

React Pre-rendering and Potential Hydration Issue
This is why I write this article about React, SSR and Hydration. It should help others understanding (and my future self) the issue....
Read more >
Keeping Server-Side Rendering Cool With React Hydration
The purpose of this article is to share some helpful things to keep in mind to render a seamless experience as a Server-Side...
Read more >
Understanding Hydration in React applications(SSR)
Hydration is used only with server-side rendering (SSR). It is a process of rendering our components and attaching event handlers.
Read more >
Server-Side Rendering (SSR) - Vue.js
To make the client-side app interactive, Vue needs to perform the hydration step. During hydration, it creates the same Vue application that was...
Read more >
Client-side vs. Server-side vs. Pre-rendering for Web Apps
In this article, Toptal Freelance Front-end Developer Guillaume Breux compares client-side, server-side, and pre-rendering strategies to help you choose the ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found