Styled-components: Client style missing on hydration after SSR (V5)

Created on 16 Oct 2019  ·  42Comments  ·  Source: styled-components/styled-components

Environment

## System:
 - OS: macOS High Sierra 10.13.4
 - CPU: (4) x64 Intel(R) Core(TM) i7-6567U CPU @ 3.30GHz
 - Memory: 82.61 MB / 16.00 GB
 - Shell: 3.2.57 - /bin/bash
## Binaries:
 - Node: 8.12.0 - ~/.nvm/versions/node/v8.12.0/bin/node
 - Yarn: 1.6.0 - /usr/local/bin/yarn
 - npm: 6.4.1 - ~/.nvm/versions/node/v8.12.0/bin/npm
 - Watchman: 4.7.0 - /usr/local/bin/watchman
## npmPackages:
 - babel-plugin-styled-components: ^1.10.6 => 1.10.6
 - styled-components: ^5.0.0-beta.9 => 5.0.0-beta.9

Reproduction

Sandbox 1 (expressJS setup) https://codesandbox.io/s/example-server-side-rendering-fsq6v
Sandbox 2 (nextJS setup) https://codesandbox.io/s/next-styled-component-v5-style-mismatch-0n0qk

Steps to reproduce

Set up a simple button component with a gradient border.

Expected Behavior

SSR will render the gradient and upon hydration, the client will keep the gradient.

Actual Behavior

SSR will render the gradient and upon hydration, the border styling is removed.

5.0 help wanted integration

Most helpful comment

Can you unpublish [email protected]. It's being recommended as an upgrade over [email protected] by renovate.

All 42 comments

This is fixed in beta 11, apologies!

@probablyup Thanks for the update. I've updated the sandbox dependency requirements to use beta11, but it still seems to be an issue. Am I missing something?

It’s working for me in that sandbox.

@probablyup You do not see a flash on the styling of the border after refreshing a page?

I've also confirmed within our production app that the issue still manifests between SSR and client hydration.

This is very strange. It _was_ working for me.

Seems to be something with that linear gradient syntax. If you replace it with a solid color it behaves as expected... I wonder if it's a CSSOM insertRule thing.

Edit: seemingly something to do with the parens. -_-

@probablyup For what it's worth, in our app I've seen this manifest with other attributes, particularly with font styling. I could probably come up with another reproduction if it's helpful

@probablyup I can confirm, that the bug has been fixed for me with v11. Thanks for your work!

@rtymchyk if you could come up with a repro using something like nextjs that'd be awesome. For some reason that express setup is very hard to debug

@probablyup I'm not very familiar with NextJS so it will take me a bit to spin that up - is there something in particular that's making it hard to debug? I imagine this can be verified with just unit tests in the repo?

@rtymchyk the way it's bundling for development is eval-based, so you can't actually debug the library code

@probablyup I've recreated the bug within a NextJS sandbox: https://codesandbox.io/s/next-styled-component-v5-style-mismatch-0n0qk

Can I ask what other information is needed to help unblock?

Might have something to do with this: https://github.com/zeit/next.js/issues/9070

Given that it was reproducing in an ExpressJS setup, I'm not sure how the NextJS bug is relevant, but I could be wrong.

Ah right, sorry there have been a lot of similar but slightly different issues around this topic and I got confused.

I've been digging into this and it appears to be an issue with reading back out of CSSOM. cssRule.cssText doesn't like that border image syntax for some reason... I'm fiddling around with it.

@probablyup thanks for digging!

More interesting... it's correct in Safari and Edge, and wrong in Chrome and Firefox... oy vey lol. So it seems there are vendor-specific bugs in the implementation that we're catching the end of.

cc @kitten

@probablyup why the difference between v5 and v4?

Reproduction:

  1. Go to a page and create a style element in head with this content:
<style id="style-test">
    .a{border:none;font-size:36px;border-image:linear-gradient(315deg,#fff8c5,#fdb3e4);border-width:3px;border-style:solid;border-image-slice:1;background-color:white;}
</style>
  1. Go to your console and inspect it:
document.getElementById("style-test").sheet.cssRules[0]
  1. Notice that .cssText is missing the border-image declaration, but if you access the style property it's actually there:
document.getElementById("style-test").sheet.cssRules[0].style['border-image']

@rtymchyk oh rehydration was totally rewritten for v5, that's part of the reason for our performance gains over v4

In the meantime we need a different way of pulling out those styles @kitten since a bugfix may never come

More interesting... it's correct in Safari and Edge, and wrong in Chrome and Firefox... oy vey lol. So it seems there are vendor-specific bugs in the implementation that we're catching the end of.

cc @kitten

Have you tried the new Edge, that runs on Chromium? I expect that it'll also have the bug, since it doesn't work in Chrome.

Oh wow, this is a weird one! We’ll have to take a closer look but it’s probably non-obvious how we could work around this

@omBratteng I'm sure it would too yeah. Looks like engs on both Chromium and FF are looking into the filed bugs already so perhaps a fix will land in the near future... though it'll be several months or more before most users are updated.

~I just ran into the same issue on iOS (11, 12 and 13).~

Nvm. seems to be an Issue in 4.x aswell, might be something I screwed up.

I'm working on a regex-based fix for this, going to try and get a PR up tonight

@probablyup just a heads up; if you're thinking of replacing the rehydration with a manual text parser/splitter like in v4, we'll probably regress on performance again 😢 It was pretty bad before, and the CSSOM rehydration improved rehydration performance by an entire order of magnitude

@rtymchyk Could you try out [email protected] and let me know how it goes?

@probablyup as far as I can tell, the branch fixes the issue

Should be fixed in rc2! :)

Thank you!

Can you unpublish [email protected]. It's being recommended as an upgrade over [email protected] by renovate.

Just my 2 cents about this one. According to npm semver - prereleases are “sorted” alphabetically, so “regexhydrate” is considered to be “newer” than “rc”. Similar thing has happened to Rx in the past.

Same here using yarn upgrade-interactive:

yarn upgrade-interactive v1.21.1
info Color legend : 
 "<red>"    : Major Update backward-incompatible updates 
 "<yellow>" : Minor Update backward-compatible features 
 "<green>"  : Patch Update backward-compatible bug fixes
? Choose which packages to update. (Press <space> to select, <a> to toggle all, <i> to invert selection)
 dependencies
   name               range        from           to                    url
❯◯ styled-components  ^5.0.0-rc.3  5.0.0-rc.3  ❯  5.0.0-regexrehydrate  https://styled-components.com/

5.0.0-regexrehydrate

That’s an old version from before the RCs. Please just use the “beta” tag
in your package json.

On Wed, Jan 8, 2020 at 4:01 AM Pierre Bondoerffer notifications@github.com
wrote:

Same here using yarn upgrade-interactive:

yarn upgrade-interactive v1.21.1

info Color legend :

"" : Major Update backward-incompatible updates

"" : Minor Update backward-compatible features

"" : Patch Update backward-compatible bug fixes
? Choose which packages to update. (Press to select, to toggle all, to invert selection)

dependencies

name range from to url

❯◯ styled-components ^5.0.0-rc.3 5.0.0-rc.3 ❯ 5.0.0-regexrehydrate https://styled-components.com/


You are receiving this because you modified the open/close state.

Reply to this email directly, view it on GitHub
https://github.com/styled-components/styled-components/issues/2812?email_source=notifications&email_token=AAELFVVOIVESA34ZT4JQS5LQ4WI5ZA5CNFSM4JBNMT32YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEILVF5I#issuecomment-571953909,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAELFVQOBIQPCO676HXWIZLQ4WI5ZANCNFSM4JBNMT3Q
.

What version should I use to fix this? 5.0.1 seems to have this problem (I'm using Gatsby)

5.1.1 still has this problem for me. I get this error:

Warning: Prop `breakpoint` did not match. Server: "0" Client: "3"

For context, breakpoint is a custom prop I'm passing to my styled component. It's determined using window size, and it isn't the same on server & client by design.

When the client loads, it doesn't seem to rehydrate the style. However, the proper style logs to the client developer tools.

Even though I have the babel plugin set up for next.js

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JamieDixon picture JamieDixon  ·  42Comments

robbue picture robbue  ·  42Comments

brad-decker picture brad-decker  ·  66Comments

Nemsae picture Nemsae  ·  65Comments

probablyup picture probablyup  ·  68Comments