Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use with Gatsby? (Styles not loading on static-site generation) #53

Closed
Deckstar opened this issue Jan 14, 2022 · 3 comments
Closed

Comments

@Deckstar
Copy link

Hey 😄 Sorry to bother, but I'm quite confused.

I've been trying to use this library with Gatsby JS (a popular static site generation framework, similar to Next JS). I've messed around with gatsby-plugin-emotion and gatsby-plugin-material-ui, but my styles never seem to be server-side rendered in production mode — when I run gatsby serve and then open up the page, there is always a "flash of unstyled content".

I'm guessing the problem is that the SSG side doesn't have access to the emotion cache from tss-react? The Gatsby documentation has a page for emotion but they don't mention anything about a custom cache, so I'm a bit stuck unfortunately 😅

Would it perhaps be possible to have an example of a tss-react setup with Gatbsy? I'm sure it would be helpful to lots of people 😄

Best,

@garronej
Copy link
Owner

Hi @Deckstar,

Maybe this can help:

import { getTssDefaultEmotionCache } from "tss-react";
const cache = getTssDefaultEmotionCache();

https://ntsim.uk/posts/how-to-add-vanilla-emotion-ssr-to-gatsby

Let me know if it help. Otherwise please share a sample project with me so I can test.

Best regards

@Deckstar
Copy link
Author

Hey! Just wanted to say thanks a lot for the very quick help! :)

It took me a while but I finally solved the issue by combining the code snippet & blog post you posted with some code from the Gatsby Material UI plugin. Basically I had to copy paste most of that plugin into my own gatsby-ssr.js file.

I will try to post my full solution here this weekend and then I think we can close this issue 😄

@Deckstar
Copy link
Author

Deckstar commented Jan 29, 2022

Hello again!

I described my solution for this problem in this blog post. Here's a summary in case someone is reading it here 😄


TLDR:

  • copy paste the two files below
  • make sure your <CacheProvider /> component imports your emotion cache from the new place
  • remove gatsby-plugin-material-ui from your gatsby-node.js file if you had it

./src/theme/cache.js:

import createCache from '@emotion/cache';

/** @type {import('@emotion/cache').Options} */
export const cacheProps = {
	key: 'mui',
	prepend: true,
};

/** @type {import("@emotion/cache").EmotionCache | undefined} */
export let muiCache;

export const makeMuiCache = () => {
	if (!muiCache) {
	muiCache = createCache(cacheProps);
	}

	return muiCache;
};

./gatsby-srr.js:

import { CacheProvider } from '@emotion/react';
import createEmotionServer from '@emotion/server/create-instance';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { getTssDefaultEmotionCache } from 'tss-react';

import { makeMuiCache } from './src/theme/cache';

/** @param {import('gatsby').ReplaceRendererArgs} args */
export const replaceRenderer = (args) => {
  const { bodyComponent, replaceBodyHTMLString, setHeadComponents } = args;

  const muiCache = makeMuiCache();
  const { extractCriticalToChunks } = createEmotionServer(muiCache);

  const emotionStyles = extractCriticalToChunks(
    renderToString(
      <CacheProvider value={muiCache}>{bodyComponent}</CacheProvider>
    )
  );

  const muiStyleTags = emotionStyles.styles.map((style) => {
    const { css, key, ids } = style || {};
    return (
      <style
        key={key}
        data-emotion={`${key} ${ids.join(` `)}`}
        dangerouslySetInnerHTML={{ __html: css }}
      />
    );
  });

  const tssCache = getTssDefaultEmotionCache();
  const { extractCritical } = createEmotionServer(tssCache);
  const { css, ids } = extractCritical(renderToString(bodyComponent));

  const tssStyleTag = (
    <style
      key="tss-styles"
      data-emotion={`css ${ids.join(' ')}`}
      dangerouslySetInnerHTML={{ __html: css }}
    />
  );

  const combinedStyleTags = [...muiStyleTags, tssStyleTag];
  setHeadComponents(combinedStyleTags);

  // render the result from `extractCritical`
  replaceBodyHTMLString(emotionStyles.html);
};

Don't forget to delete the Gatsby Material UI plugin if you were using it!

./gatsby-config.js:

module.exports = {
 /* Your site config here */
 plugins: [
   `gatsby-plugin-material-ui`, // <-- delete me!
	// ...rest plugins
 ],
 // ...rest config
};

And that's it 😄

Thanks again for the help!

gitbook-com bot pushed a commit that referenced this issue Mar 6, 2022
gitbook-com bot pushed a commit that referenced this issue Oct 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants