首页 > 解决方案 > 带有 Material-UI 的 SSR 上的 @emotion/cache 始终为空

问题描述

我将我的 React SSR 从纯 @emotion 切换到 material-ui 5.0,但不再提取样式。ID 提取createExtractCriticalToChunks效果很好,但是来自情感的 cache.inserted 对象现在始终是一个空对象。我在这里做错了什么?

 "@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>

提取的ID:

{
  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
}

缓存:

{
  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
}

缓存设置 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);

服务器应用程序.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/

标签: javascriptmaterial-uiserver-side-renderingemotionemotion-js

解决方案


好的,所以我发现了我的问题并能够解决它。

似乎在我从材料 4 升级到 mui 5 之后,其中一个 codemods 将我的代码包装在 a<StyledEngineProvider>中以启用样式组件 ssr 并且该提供程序还用 实例化了一个 EmotionCache key:'css',因此它与emotionCache我添加的自定义冲突。一旦我删除了<StyledEngineProvider>包装器,所有样式都从 ssr 中返回。


推荐阅读