Fixing styled-components server-side-rendering issues in Gatsby
How to fix styled-components ssr issues in Gatsby production build
My Problem ⚠️
In the development environment everything was working fine, but after building the Gatsby site, an annoying flickering effect appeared where styles from styled-components where being applied with delay, like shown in the gif above.
Although that’s the problem I personally encountered, it could also happen that your app is ignoring some or all styles from styled-components.
We’ll see why this happens and how to troubleshoot it.
My initial approach 👎
My initial thoughts were: ”what the hell is going on!¿?@!$¿¡!”.
Finding out that people had similar issues with Gatsby having different behaviour between development and production builds¹², and that it was related to rehydration, was a relief.
If you want to know more about Gatsby and hydration, you may have a look to it at Gatsby Docs³.
Then I discovered an awesome post about rehydration problems server-side-rendering (ssr) React apps like Gatsby⁴ and I thought: ”hmmm… this should work for me”. And it did! It looked like a rehydration problem, so if I waited for the client (React) to be ready, then the styles would be applied when the content is painted on the screen. Nice, problem solved!
Though this approach is cool if we intend to solve small rehydration issues in some specific components, it is not for the entire app. If you do that, you’re taking no advantage of ssr, which very briefly is 1) bad for performance and 2) bad for SEO⁵.
So, after quite a bit of debugging, research and gaining more knowledge on Gatsby, I was able to solve the problem in a more elegant way (in fact, the proper way of solving it) while taking advantage of ssr.
Solutions ✅
Next you’ll find different solutions I tried, which seem to be useful for most common issues users have with styled-components and Gatsby.
1. Check you have gatsby-styled-components
& babel-plugin-styled-components
` installed. Styled-components will not work without them in ssr⁶.
2. Check that each css property ends with a semicolon and there are no css typos like closing a line with double semicolon ;;
⁷.
3. Check your are properly using wrapRootElement
and wrapPageElement
APIs. The first is “useful to set up any Provider components that will wrap your application” and the second one ”set persistent UI elements around pages”. See Gatsby docs for more info about those APIs⁸.
4. If you use wrapRootElement
and wrapPageElement
, don’t forget to implement it both in gatsby-browser.js
and gatsby-ssr.js
.
In my case, checking solutions 2 and 3 helped me to fix the issue. As an example, my gatsby-browser.js
and gatsby-ssr.js
ended up sharing the following code:
Conclusions
The problem described seems to be a very common pitfall in the first steps in Gatsby, and it can become difficult and tedious to debug and find the right solution. So in case you came here looking for help, I hope this post has been helpful to you.
Finally, facing this type of issues teaches how not to overestimate development environments, because even if everything works fine in development, many things can go wrong in production!
References
[1] https://github.com/gatsbyjs/gatsby/issues/10706
[2] https://github.com/gatsbyjs/gatsby/discussions/17914
[3] https://www.gatsbyjs.com/docs/glossary/hydration/
[4] https://www.joshwcomeau.com/react/the-perils-of-rehydration/
[6] https://www.gatsbyjs.com/plugins/gatsby-plugin-styled-components/
[7] https://github.com/gatsbyjs/gatsby/issues/16039
[8] https://www.gatsbyjs.com/docs/reference/config-files/gatsby-ssr/#wrapPageElement