gatsbyjs / gatsby

The best React-based framework with performance, scalability and security built in.
https://www.gatsbyjs.com
MIT License
55.29k stars 10.31k forks source link

gatsby-plugin-emotion with custom ThemeProvider not injecting on SSR #17894

Closed zslabs closed 5 years ago

zslabs commented 5 years ago

Description

https://github.com/zslabs/zslabs.com has gatsby-plugin-emotion along with a custom Cache and ThemeProvider in both gatsby-browser and gatsby-ssr. Production builds and hard-refreshing an article page (since the homepage has some animations that hide things by default) such as https://zslabs.com/articles/list-ebay-search-toolkit shows a flash of unstyled content when it all be inlined. Only the <Global /> styles are inlined; which is not what is described from the plugin features.

Minimal reproduction

https://github.com/zslabs/gatsby-emotion-ssr

Steps to reproduce

☝️ Example repo and production version to reproduce is available above.

Expected result

All styles should be inlined.

Actual result

Only <Global /> styles are.

amitnovick commented 5 years ago

Hi Zach, Have to say, your site looks great! good job 👍.

As for the issue at hand: I have a strong feeling that the following will let SSR work for your app: This is an adaptation from your website's homepage code:

import { css } from '@emotion/core';

// ...

const Index = () => {
  // ...
  return (
  /* ... */
        <div css=css({{ textAlign: 'center' }})>
  /* ... */
  );
};
amitnovick commented 5 years ago

UPDATE: Just realized Emotion actually is supposed to also support direct passing of object styles, which is exactly what you're doing in your code already.

Therefore, the plugin isn't working properly for this feature of Emotion, and this issue has merit.

LekoArts commented 5 years ago

You are missing the mandatory dependencies @emotion/core @emotion/styled emotion-theming in your project. Please add those and see if it works.

zslabs commented 5 years ago

You are missing the mandatory dependencies @emotion/core @emotion/styled emotion-theming in your project. Please add those and see if it works.

Thanks for the reply. The deps are coming from https://github.com/gremlin/chaoskit/blob/feature/emotion/package.json and you can confirm in my repo’s lock file.

Could you elaborate why I’d need @emotion/styled when I’m not using it anywhere?

LekoArts commented 5 years ago

Ok, great! Didn't have time to check it in more detail but then the obvious thing is out of the way. In your case @emotion/styled isn't needed then.

Can you provide a minimal reproduction without all the chaoskit stuff and other dependencies. There is too much going on in the repository you linked in order to be able to debug this in a correct manner. Would be highly appreciated! Thanks :)

zslabs commented 5 years ago

https://github.com/zslabs/gatsby-emotion-ssr is the reproduction repo.

Screen Shot 2019-09-26 at 2 58 59 PM

The Header and Footer styles do not show up via SSR if you yarn && yarn build-serve this project.

You can also use https://gatsby-emotion-ssr.netlify.com and hard refresh / or /test to see the same issue. View page source (not in inspect element) shows the styles are not inlined.

cc @tkh44

zslabs commented 5 years ago

☝️ Updated example above with example that shows the issue locally for me.

zslabs commented 5 years ago

@LekoArts I know you may be looking at this already, but just wanted to confirm you did receive the last notification about the example site/repo. Thanks!

zslabs commented 5 years ago

It's been about a week since I shared the minimal reproduction - is there any other info I can provide to make this issue a bit more clear?

tmm commented 5 years ago

Just chiming in to say that I have the same issue. Thanks @zslabs for reporting and adding the example!

zslabs commented 5 years ago

Just chiming in to say that I have the same issue. Thanks @zslabs for reporting and adding the example!

Thanks for confirming you're running into that as well @tmm!

tkh44 commented 5 years ago

I worked with @zslabs on trying to diagnose the core issue here and wasn't able to pin it down. My best guess is that gastby is using the @emotion/core/dist/browser.ems.js when compiling for ssr when it should be using core.esm.js.

@mitchellhamilton would you happen to have any idea whats going on here?

emmatown commented 5 years ago

You need to create a new cache per server render and then it should work.(though the cache should be created before hydration on the client, i.e. outside of the React tree)

As an example, @zslabs if you applied this diff to your example, it would work:

diff --git a/gatsby-browser.js b/gatsby-browser.js
index a808b25..5094c16 100644
--- a/gatsby-browser.js
+++ b/gatsby-browser.js
@@ -2,11 +2,13 @@ import PropTypes from 'prop-types';
 import { ThemeProvider } from 'emotion-theming';
 import { CacheProvider } from '@emotion/core';

-import { ckCache } from './utils/Wrapper';
+import { createCkCache } from './utils/Wrapper';
 import { theme } from './utils/theme';

+const cache = createCkCache();
+
 export const wrapPageElement = ({ element }) => (
-  <CacheProvider value={ckCache}>
+  <CacheProvider value={cache}>
     <ThemeProvider theme={theme}>{element}</ThemeProvider>
   </CacheProvider>
 );
diff --git a/gatsby-ssr.js b/gatsby-ssr.js
index a808b25..ccf2b6e 100644
--- a/gatsby-ssr.js
+++ b/gatsby-ssr.js
@@ -2,11 +2,11 @@ import PropTypes from 'prop-types';
 import { ThemeProvider } from 'emotion-theming';
 import { CacheProvider } from '@emotion/core';

-import { ckCache } from './utils/Wrapper';
+import { createCkCache } from './utils/Wrapper';
 import { theme } from './utils/theme';

 export const wrapPageElement = ({ element }) => (
-  <CacheProvider value={ckCache}>
+  <CacheProvider value={createCkCache()}>
     <ThemeProvider theme={theme}>{element}</ThemeProvider>
   </CacheProvider>
 );
diff --git a/utils/Wrapper.js b/utils/Wrapper.js
index 251fbcf..774748f 100644
--- a/utils/Wrapper.js
+++ b/utils/Wrapper.js
@@ -1,6 +1,6 @@
 import createCache from '@emotion/cache';

-export const ckCache = createCache({
+export const createCkCache = () => createCache({
   key: 'ck',
   // Only prefix the following style properties
   prefix: key => {
zslabs commented 5 years ago

Thank you very much @mitchellhamilton - that was it! Will make sure we get some docs updated as well so others don't run into this. Really appreciate the help!