Search code examples
javascriptmaterial-uiserver-side-renderingemotionemotion-js

@emotion/cache on SSR with Material-UI is always empty


I switched my React SSR from pure @emotion to material-ui 5.0, but the styles won't be extracted anymore. The ID extraction in createExtractCriticalToChunks work well, but the cache.inserted object from emotion is now always an empty object. What I'm doing wrong here?

 "@emotion/babel-plugin": "^11.3.0",
 "@emotion/cache": "^11.6.0",
 "@emotion/core": "11.0.0",
 "@emotion/css": "^11.5.0",
 "@emotion/react": "^11.6.0",
 "@emotion/server": "^11.4.0",
 "@emotion/styled": "^11.6.0",
 "@mui/icons-material": "5.0.0",
 "@mui/lab": "5.0.0-alpha.47",
 "@mui/material": "5.0.0",
 "@mui/styles": "5.0.0",
 "@mui/utils": "5.0.0",
 "@mui/x-data-grid": "5.0.0-beta.1",

HTML:

<style data-emotion="css-global 1vs7qi2">html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;box-sizing:border-box;-webkit-text-size-adjust:100%;}*,*::before,*::after{box-sizing:inherit;}strong,b{font-weight:700;}body{margin:0;color:#29343D;line-height:1.5;font-size:1rem;font-family:Inter,sans-serif;font-weight:400;background-color:#fff;}@media print{body{background-color:#fff;}}body::backdrop{background-color:#fff;}</style><style data-emotion="css-global 1vs7qi2">html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;box-sizing:border-box;-webkit-text-size-adjust:100%;}*,*::before,*::after{box-sizing:inherit;}strong,b{font-weight:700;}body{margin:0;color:#29343D;line-height:1.5;font-size:1rem;font-family:Inter,sans-serif;font-weight:400;background-color:#fff;}@media print{body{background-color:#fff;}}body::backdrop{background-color:#fff;}</style><style data-emotion="css-global r7h3of">*{margin:0;padding:0;box-sizing:border-box;}html{width:100%;height:100%;-webkit-overflow-scrolling:touch;}body{width:100%;height:100%;}#root{width:100%;height:100%;}input[type=number]{-moz-appearance:textfield;}input[type=number]::-webkit-outer-spin-button{margin:0;-webkit-appearance:none;}input[type=number]::-webkit-inner-spin-button{margin:0;-webkit-appearance:none;}textarea::-webkit-input-placeholder{color:#919FAB;}textarea::-moz-placeholder{opacity:1;color:#919FAB;}textarea:-ms-input-placeholder{color:#919FAB;}textarea::-webkit-input-placeholder{color:#919FAB;}textarea::-moz-placeholder{color:#919FAB;}textarea:-ms-input-placeholder{color:#919FAB;}textarea::placeholder{color:#919FAB;}img{display:block;max-width:100%;}.blur-up{-webkit-filter:blur(5px);-webkit-filter:blur(5px);filter:blur(5px);-webkit-transition:filter 400ms,-webkit-filter 400ms;transition:filter 400ms,-webkit-filter 400ms;}.blur-up.lazyloaded{-webkit-filter:blur(0);-webkit-filter:blur(0);filter:blur(0);}</style><style data-emotion="css khurd4">.css-khurd4{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;box-sizing:border-box;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;position:fixed;z-index:1100;top:0;left:auto;right:0;background-color:#2757E7;color:#FFFFFF;box-shadow:none;background-color:transparent;}@media print{.css-khurd4{position:absolute;}}</style><style data-emotion="css 1ure1x2">.css-1ure1x2{background-color:#fff;color:#29343D;-webkit-transition:box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;transition:box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;box-shadow:0px 2px 4px -1px rgba(117, 134, 150, 0.2),0px 4px 5px 0px rgba(117, 134, 150, 0.14),0px 1px 10px 0px rgba(117, 134, 150, 0.12);background-image:none;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;box-sizing:border-box;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;position:fixed;z-index:1100;top:0;left:auto;right:0;background-color:#2757E7;color:#FFFFFF;box-shadow:none;background-color:transparent;}@media print{.css-1ure1x2{position:absolute;}}</style><header class="MuiPaper-root MuiPaper-elevation MuiPaper-elevation4 MuiAppBar-root MuiAppBar-colorPrimary MuiAppBar-positionFixed mui-fixed css-1ure1x2"><style data-emotion="css z6j3jx">.css-z6j3jx{height:64px;-webkit-transition:height 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,background-color 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;transition:height 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,background-color 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;}@media (min-width:900px){.css-z6j3jx{height:88px;}}</style><style data-emotion="css pcpmlt">.css-pcpmlt{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;min-height:56px;height:64px;-webkit-transition:height 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,background-color 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;transition:height 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,background-color 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;}@media (min-width:0px) and (orientation: landscape){.css-pcpmlt{min-height:48px;}}@media (min-width:600px){.css-pcpmlt{min-height:64px;}}@media (min-width:900px){.css-pcpmlt{height:88px;}}</style><div class="MuiToolbar-root MuiToolbar-regular css-pcpmlt"><style data-emotion="css 1hmw7xh">.css-1hmw7xh{width:100%;margin-left:auto;box-sizing:border-box;margin-right:auto;display:block;padding-left:16px;padding-right:16px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}@media (min-width:600px){.css-1hmw7xh{padding-left:24px;padding-right:24px;}}@media (min-width:1200px){.css-1hmw7xh{max-width:1200px;}}</style><div class="MuiContainer-root MuiContainer-maxWidthLg css-1hmw7xh"><a href="/"><style data-emotion="css 1880q5z">.css-1880q5z{width:100%;height:30px;}</style><div class="MuiBox-root css-1880q5z"><style data-emotion="css s08p0c">.css-s08p0c{width:100%;height:100%;}</style><img src="/assets/img/logo.svg" alt="Logo" class="css-s08p0c"/></div></a><style data-emotion="css i9gxme">.css-i9gxme{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}</style><div class="MuiBox-root css-i9gxme"></div><style data-emotion="css 1xhj18k">.css-1xhj18k{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;}</style><div class="css-1xhj18k"><style data-emotion="css 1kqvewx">.css-1kqvewx{font-weight:600;line-height:1.5714285714285714;font-size:0.875rem;font-family:Inter,sans-serif;color:#29343D;margin-right:40px;-webkit-transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;color:#fff;}.css-1kqvewx:hover{opacity:0.48;-webkit-text-decoration:none;text-decoration:none;}.css-1kqvewx.active{color:#2757E7;}</style><style data-emotion="css 1upck6y">.css-1upck6y{-webkit-text-decoration:none;text-decoration:none;font-weight:600;line-height:1.5714285714285714;font-size:0.875rem;font-family:Inter,sans-serif;color:#29343D;margin-right:40px;-webkit-transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;color:#fff;}.css-1upck6y:hover{-webkit-text-decoration:underline;text-decoration:underline;}.css-1upck6y:hover{opacity:0.48;-webkit-text-decoration:none;text-decoration:none;}.css-1upck6y.active{color:#2757E7;}</style><style data-emotion="css 1453tg1">.css-1453tg1{margin:0;color:#2757E7;-webkit-text-decoration:none;text-decoration:none;font-weight:600;line-height:1.5714285714285714;font-size:0.875rem;font-family:Inter,sans-serif;color:#29343D;margin-right:40px;-webkit-transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;color:#fff;}.css-1453tg1:hover{-webkit-text-decoration:underline;text-decoration:underline;}.css-1453tg1:hover{opacity:0.48;-webkit-text-decoration:none;text-decoration:none;}.css-1453tg1.active{color:#2757E7;}</style><a aria-current="page" class="MuiTypography-root MuiTypography-inherit MuiLink-root MuiLink-underlineHover css-1453tg1 active" href="/">Home</a><a class="MuiTypography-root MuiTypography-inherit MuiLink-root MuiLink-underlineHover css-1453tg1" href="/components">Components</a><style data-emotion="css qlki83">.css-qlki83{font-weight:600;line-height:1.5714285714285714;font-size:0.875rem;font-family:Inter,sans-serif;color:#29343D;margin-right:40px;-webkit-transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;cursor:pointer;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#fff;}.css-qlki83:hover{opacity:0.48;-webkit-text-decoration:none;text-decoration:none;}</style><style data-emotion="css 11y7onl">.css-11y7onl{-webkit-text-decoration:none;text-decoration:none;font-weight:600;line-height:1.5714285714285714;font-size:0.875rem;font-family:Inter,sans-serif;color:#29343D;margin-right:40px;-webkit-transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;cursor:pointer;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#fff;}.css-11y7onl:hover{-webkit-text-decoration:underline;text-decoration:underline;}.css-11y7onl:hover{opacity:0.48;-webkit-text-decoration:none;text-decoration:none;}</style><style data-emotion="css 1d3jie5">.css-1d3jie5{margin:0;color:#2757E7;-webkit-text-decoration:none;text-decoration:none;font-weight:600;line-height:1.5714285714285714;font-size:0.875rem;font-family:Inter,sans-serif;color:#29343D;margin-right:40px;-webkit-transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;cursor:pointer;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#fff;}.css-1d3jie5:hover{-webkit-text-decoration:underline;text-decoration:underline;}.css-1d3jie5:hover{opacity:0.48;-webkit-text-decoration:none;text-decoration:none;}</style><a class="MuiTypography-root MuiTypography-inherit MuiLink-root MuiLink-underlineHover css-1d3jie5">Pages<style data-emotion="css 5odfsb">.css-5odfsb{margin-left:4px;width:16px;height:16px;}</style><span></span></a></div><style data-emotion="css vxcmzt">.css-vxcmzt{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;}</style><div class="MuiBox-root css-vxcmzt"><style data-emotion="css 1q8kglw">.css-1q8kglw{text-align:center;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;font-size:1.5rem;padding:8px;border-radius:50%;overflow:visible;color:#637381;-webkit-transition:background-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;transition:background-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;margin-left:8px;color:#fff;}.css-1q8kglw:hover{background-color:rgba(99, 115, 129, 0.08);}@media (hover: none){.css-1q8kglw:hover{background-color:transparent;}}.css-1q8kglw.Mui-disabled{background-color:transparent;color:rgba(145, 159, 171, 0.8);}</style><style data-emotion="css f1sec2">.css-f1sec2{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;position:relative;box-sizing:border-box;-webkit-tap-highlight-color:transparent;background-color:transparent;outline:0;border:0;margin:0;border-radius:0;padding:0;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;-moz-appearance:none;-webkit-appearance:none;-webkit-text-decoration:none;text-decoration:none;color:inherit;text-align:center;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;font-size:1.5rem;padding:8px;border-radius:50%;overflow:visible;color:#637381;-webkit-transition:background-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;transition:background-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;margin-left:8px;color:#fff;}.css-f1sec2::-moz-focus-inner{border-style:none;}.css-f1sec2.Mui-disabled{pointer-events:none;cursor:default;}@media print{.css-f1sec2{-webkit-print-color-adjust:exact;color-adjust:exact;}}.css-f1sec2:hover{background-color:rgba(99, 115, 129, 0.08);}@media (hover: none){.css-f1sec2:hover{background-color:transparent;}}.css-f1sec2.Mui-disabled{background-color:transparent;color:rgba(145, 159, 171, 0.8);}</style><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium css-f1sec2" tabindex="0" type="button"><span></span></button></div><style data-emotion="css bv0lr">.css-bv0lr{z-index:1200;}.css-bv0lr[role="presentation"] .MuiDrawer-paperAnchorLeft{box-shadow:8px 24px 24px 12px rgba(22, 29, 36, 0.16);}.css-bv0lr[role="presentation"] .MuiDrawer-paperAnchorRight{box-shadow:-8px 24px 24px 12px rgba(22, 29, 36, 0.16);}</style></div></div></header><div><style data-emotion="css 10klw3m">.css-10klw3m{height:100%;}</style><style data-emotion="css w8rns">.css-w8rns{height:100%;}</style><div class="MuiBox-root css-w8rns" id="move_top"><style data-emotion="css 6ipfk0">.css-6ipfk0{overflow:hidden;position:relative;background-color:#fff;}</style><div class="css-6ipfk0"><style data-emotion="css 17r9e7a">.css-17r9e7a{padding-top:120px;}@media (min-width:900px){.css-17r9e7a{padding-bottom:120px;}}</style><div class="css-17r9e7a"><style data-emotion="css 1m534n9">.css-1m534n9{width:100%;margin-left:auto;box-sizing:border-box;margin-right:auto;display:block;padding-left:16px;padding-right:16px;}@media (min-width:600px){.css-1m534n9{padding-left:24px;padding-right:24px;}}@media (min-width:1200px){.css-1m534n9{max-width:1200px;}}</style><div class="MuiContainer-root MuiContainer-maxWidthLg css-1m534n9"><style data-emotion="css 17dd4p5">@media (min-width:0px){.css-17dd4p5{margin-bottom:80px;}}@media (min-width:900px){.css-17dd4p5{margin-bottom:200px;}}</style><div class="MuiBox-root css-17dd4p5"><ul><li><a href="/auth/login">Login</a></li><li><a href="/auth/logout">Logout</a></li><li><a href="/components">Components</a></li><li><a href="/dashboard">Dashboard</a></li></ul></div></div></div></div></div></div><style data-emotion="css jw1ye2">.css-jw1ye2{padding-top:40px;padding-bottom:40px;text-align:center;position:relative;background-color:#fff;}</style><div class="MuiBox-root css-jw1ye2"><div class="MuiContainer-root MuiContainer-maxWidthLg css-1m534n9"><a><style data-emotion="css u7kbj0">.css-u7kbj0{width:100%;height:30px;margin-bottom:8px;margin-left:auto;margin-right:auto;cursor:pointer;}</style><div class="MuiBox-root css-u7kbj0"><img src="/assets/img/logo.svg" alt="Logo" class="css-s08p0c"/></div></a></div></div>

Extracted ID's:

{
  global: true,
  khurd4: true,
  '1ure1x2': true,
  z6j3jx: true,
  pcpmlt: true,
  '1hmw7xh': true,
  '1880q5z': true,
  s08p0c: true,
  i9gxme: true,
  '1xhj18k': true,
  '1kqvewx': true,
  '1upck6y': true,
  '1453tg1': true,
  qlki83: true,
  '11y7onl': true,
  '1d3jie5': true,
  '5odfsb': true,
  vxcmzt: true,
  '1q8kglw': true,
  f1sec2: true,
  bv0lr: true,
  '10klw3m': true,
  w8rns: true,
  '6ipfk0': true,
  '17r9e7a': true,
  '1m534n9': true,
  '17dd4p5': true,
  jw1ye2: true,
  u7kbj0: true
}

Cache:

{
  key: 'css',
  sheet: e {
    _insertTag: [Function (anonymous)],
    isSpeedy: false,
    tags: [],
    ctr: 0,
    nonce: undefined,
    key: 'css',
    container: undefined,
    prepend: true,
    insertionPoint: undefined,
    before: null
  },
  nonce: undefined,
  inserted: {},
  registered: {},
  insert: [Function: o],
  compat: true
}

Cache Setup SSR:

let key = 'css';
let serverCache = createCache({ key: key, prepend: true, speedy: false });
const { extractCriticalToChunks, constructStyleTagsFromChunks, extractCritical } = createEmotionServer(serverCache);

const body = ReactDOMServer.renderToString(
  <ChunkExtractorManager extractor={webExtractor}>
    <ServerApp url={url} context={serverContext} helmetContext={helmetContext} store={storage.store} serverCache={serverCache}/>
  </ChunkExtractorManager>,
)

const emotionStyles = extractCriticalToChunks(body);
const emotionCss = constructStyleTagsFromChunks(emotionStyles);

ServerApp.js

<CacheProvider value={serverCache}>
  <IntlProvider locale={config.locale} messages={localeMessages} textComponent="span">
    <Provider store={store}>
      <HelmetProvider context={helmetContext}>
        <ThemeConfig>
          <ThemePrimaryColor>
            <CssBaseline />
            <GlobalStyles />
            <PersistGate loading={null} persistor={store.persistor}>
              <StaticRouter location={url} context={context}>
                <Routes routes={routeConfiguration()} />
              </StaticRouter>
            </PersistGate>
          </ThemePrimaryColor>
        </ThemeConfig >
      </HelmetProvider>
    </Provider>
  </IntlProvider>
</CacheProvider>

MUI SSR: https://mui.com/guides/server-rendering/


Solution

  • Ok, so I found my issue and was able to fix it.

    Seems that after I upgraded from material 4 to mui 5 one of the codemods was wrapping up my code inside a <StyledEngineProvider> to enable the styled components ssr and that provider also instantiates an emotionCache with key:'css', so it was conflicting with the custom emotionCache I was adding. Once I removed the <StyledEngineProvider> wrapper all the styles are back from the ssr.