Styled-jsx: FOUC in Safari

Created on 23 Dec 2016  Â·  15Comments  Â·  Source: vercel/styled-jsx

After converting a site to next@beta and styled-jsx, I started to notice a FOUC in Safari when I transitioned pages.

Having already looked at styled-jsx my hunch was the rAF callback that updates the styles in the DOM is called in a different order in Safari than Chrome. I set a break-point within the rAF callback in both Safari and Chrome and sure enough the order of operations is different.

Chrome:

  1. unmount outgoing <style jsx> components
  2. render incoming <style jsx> components
  3. mount incoming <style jsx> components
  4. __rAF callback fires, update <style>s in <head>__
  5. __paint__

Safari:

  1. unmount outgoing <style jsx> components
  2. render incoming <style jsx> components
  3. mount incoming <style jsx> components
  4. __paint__
  5. __rAF callback fires, update <style>s in <head>__

Safari painted the updated DOM tree before styled-jsx's rAF callback was called. While in Chrome, the rAF callback is called first, then Chrome paints. This is why I'm seeing FOUC in Safari but not in Chrome.

I didn't have time to dig into a possible solution for this, but wanted to bring it up in case this wasn't already a known issue.

bug

Most helpful comment

@nkzawa I just deployed a site on [email protected] which has your fix and Safari is working without FOUC 🎉

All 15 comments

Thanks for your report! Unfortunately, I have no idea about solutions :( Any suggestions are appreciated.

I wonder if setTimeout(fn, 0) would fix the problem 🤔

@ericf would you be so kind to test with setTimeout? That way we can sniff Safari and use one or the other

@nkzawa @rauchg I tested setTimeout(fn, 0) and the FOUC is still there in Safari __and__ it causes it to appear in Chrome as well. I'll try to think of other solutions…

Well we can always disable the raf scheduling altogether for Safari right?

@rauchg removing the scheduling does remove the FOUC in Safari, and is fine in Chrome. It seems that the scheduling was a perf optimization, is that correct? I wonder what impact there would really be to simply remove the scheduling in all browsers… did you guys test with and without rAF scheduling before adding it?

Basically, we do this to update styles only once in a batch when rendering of React occurs.
If we don't, for example, 2 next.js pages which has a same component with styled-jsx tag will work like the following.

import StyledComponent from './styled-component'
export default () => <div>page A: <StyledComponent /></div>
import StyledComponent from './styled-component'
export default () => <div>page B: <StyledComponent /></div>

When transition occurs from the page A to B:

  1. remove the style tag from head.
  2. add the same style tag to head.

I don't know if it's no problem for style tags. At least, on next/head, this causes to load a script many times.

So is it meant to coalesce? In that case you can use promise resolution to batch things in a microtask:

https://twitter.com/_developit/status/804461666083684352

I was thinking about using a promise too. I can test that tonight.

Promise#then() does work and I don't see FOUC in Chrome, Safari, or Firefox. Here's a PR: https://github.com/zeit/styled-jsx/pull/63

This issue seems to be back in Safari 😢

With the recent launch of zeit.co on the latest version of Next.js, I started to noticed the FOUC in Safari when navigating between the Dashboard and Account pages. When navigating I see a very large â–² logo which takes up the entire page.

I'm thinking that we might need to remove the scheduled style updates in Safari and update them eager.

@nkzawa @rauchg thoughts? (Also can you guys reproduce?)

Yeah we noticed this today. @nkzawa is looking into it. If you have a
solution a PR is welcome as well! Thank you

On Wed, Feb 1, 2017 at 9:24 PM Eric Ferraiuolo notifications@github.com
wrote:

This issue seems to be back in Safari 😢

With the recent launch of zeit.co on the latest version of Next.js, I
started to noticed the FOUC in Safari when navigating between the Dashboard
and Account pages. When navigating I see a very large â–² logo which takes up
the entire page.

I'm thinking that we might need to remove the scheduled style updates in
Safari and update them eager.

@nkzawa https://github.com/nkzawa @rauchg https://github.com/rauchg
thoughts? (Also can you guys reproduce?)

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/zeit/styled-jsx/issues/52#issuecomment-276871551, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAAy8TdWgSQfHQ4fnP8Jrg55DtHwGMOKks5rYWiQgaJpZM4LUlz4
.

>

– @rauchg https://twitter.com/rauchg

I'm thinking that we might need to remove the scheduled style updates in Safari and update them eager.

It seems this is the only solution as far as I investigated 😭

@nkzawa I just deployed a site on [email protected] which has your fix and Safari is working without FOUC 🎉

https://bugs.webkit.org/show_bug.cgi?id=161291 This is the reported bug on the bug tracker of Webkit. We'll be able to revert this PR when it was fixed.

Was this page helpful?
0 / 5 - 0 ratings