preactjs / preact-cli

😺 Your next Preact PWA starts in 30 seconds.
MIT License
4.69k stars 375 forks source link

Weird behaviour on pre-rendered pages with hidden components #1644

Closed orangecoloured closed 2 years ago

orangecoloured commented 2 years ago

What is the current behaviour? I have several pages with hidden for SSR render components. The pre-rendered code looks fine, but as soon as JS fires up it messes up the layout.

How the raw source code looks like:

Screenshot 2022-01-26 at 12 33 26 AM

How it looks like when the page is loaded:

Screenshot 2022-01-26 at 12 33 52 AM

The last node is duplicated and each previous node is wrapped in the next sibling's wrapping node.

Steps to Reproduce Steps to reproduce the behavior:

  1. Have a conditionally hidden component in the layout, for example testing for the window object
  2. Build the project
  3. Serve it

What is the expected behaviour? The behaviour is the same as in dev mode.

Environment Info:
  System:
    OS: macOS 12.1
    CPU: (8) x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
  Binaries:
    Node: 17.2.0 - /usr/local/bin/node
    Yarn: 1.22.17 - /usr/local/bin/yarn
    npm: 8.1.4 - /usr/local/bin/npm
  Browsers:
    Firefox: 96.0.1
    Safari: 15.2
  npmPackages:
    preact: ^10.6.4 => 10.6.4 
    preact-cli: ^3.0.0 => 3.3.3 
    preact-render-to-string: ^5.1.4 => 5.1.19 
    preact-router: ^4.0.1 => 4.0.1 
rschristian commented 2 years ago

Please provide a reproduction, what you've listed is not enough to go on.

We just hydrate over the first child if you've prerendered.

https://github.com/preactjs/preact-cli/blob/0125cc3d24e09fb96215f833921cadb4838d4f7d/packages/cli/lib/lib/entry.js#L34-L61

orangecoloured commented 2 years ago

@rschristian here you go https://github.com/orangecoloured/ssr-hidden-component-test

There's a TestComponent which renders normally while dev. When you build and then serve the project you'll notice the layout is messed up upon page load. The generated layout is correct though.

rschristian commented 2 years ago

Thanks for the reproduction, it helped me understand what you were referring to.

This is correct behavior, see https://github.com/preactjs/preact/issues/2572

Hydrate expects content to match -- it's a fast path around rendering built for this purpose. You need to make your content match, or get closer to it with placeholder elements, as full diffing isn't done.