带有 Material-UI 的 s-s-r 上的 @emotion/cache 始终为空

Posted

技术标签:

【中文标题】带有 Material-UI 的 s-s-r 上的 @emotion/cache 始终为空【英文标题】:@emotion/cache on s-s-r with Material-UI is always empty 【发布时间】:2021-12-27 00:20:17 【问题描述】:

我将我的 React s-s-r 从纯 @emotion 切换到 material-ui 5.0,但不再提取样式。 createExtractCriticalToChunks 中的 ID 提取效果很好,但是来自情感的 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,*::afterbox-sizing:inherit;strong,bfont-weight:700;bodymargin:0;color:#29343D;line-height:1.5;font-size:1rem;font-family:Inter,sans-serif;font-weight:400;background-color:#fff;@media printbodybackground-color:#fff;body::backdropbackground-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,*::afterbox-sizing:inherit;strong,bfont-weight:700;bodymargin:0;color:#29343D;line-height:1.5;font-size:1rem;font-family:Inter,sans-serif;font-weight:400;background-color:#fff;@media printbodybackground-color:#fff;body::backdropbackground-color:#fff;</style><style data-emotion="css-global r7h3of">*margin:0;padding:0;box-sizing:border-box;htmlwidth:100%;height:100%;-webkit-overflow-scrolling:touch;bodywidth:100%;height:100%;#rootwidth:100%;height:100%;input[type=number]-moz-appearance:textfield;input[type=number]::-webkit-outer-spin-buttonmargin:0;-webkit-appearance:none;input[type=number]::-webkit-inner-spin-buttonmargin:0;-webkit-appearance:none;textarea::-webkit-input-placeholdercolor:#919FAB;textarea::-moz-placeholderopacity:1;color:#919FAB;textarea:-ms-input-placeholdercolor:#919FAB;textarea::-webkit-input-placeholdercolor:#919FAB;textarea::-moz-placeholdercolor:#919FAB;textarea:-ms-input-placeholdercolor:#919FAB;textarea::placeholdercolor:#919FAB;imgdisplay: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-khurd4display:-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-khurd4position:absolute;</style><style data-emotion="css 1ure1x2">.css-1ure1x2background-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-1ure1x2position: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-z6j3jxheight: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-z6j3jxheight:88px;</style><style data-emotion="css pcpmlt">.css-pcpmltposition: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-pcpmltmin-height:48px;@media (min-width:600px).css-pcpmltmin-height:64px;@media (min-width:900px).css-pcpmltheight:88px;</style><div class="MuiToolbar-root MuiToolbar-regular css-pcpmlt"><style data-emotion="css 1hmw7xh">.css-1hmw7xhwidth: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-1hmw7xhpadding-left:24px;padding-right:24px;@media (min-width:1200px).css-1hmw7xhmax-width:1200px;</style><div class="MuiContainer-root MuiContainer-maxWidthLg css-1hmw7xh"><a href="/"><style data-emotion="css 1880q5z">.css-1880q5zwidth:100%;height:30px;</style><div class="MuiBox-root css-1880q5z"><style data-emotion="css s08p0c">.css-s08p0cwidth: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-1xhj18kdisplay:-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-1kqvewxfont-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:hoveropacity:0.48;-webkit-text-decoration:none;text-decoration:none;.css-1kqvewx.activecolor:#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:hoveropacity:0.48;-webkit-text-decoration:none;text-decoration:none;.css-1upck6y.activecolor:#2757E7;</style><style data-emotion="css 1453tg1">.css-1453tg1margin: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:hoveropacity:0.48;-webkit-text-decoration:none;text-decoration:none;.css-1453tg1.activecolor:#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-qlki83font-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:hoveropacity: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:hoveropacity:0.48;-webkit-text-decoration:none;text-decoration:none;</style><style data-emotion="css 1d3jie5">.css-1d3jie5margin: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:hoveropacity: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-5odfsbmargin-left:4px;width:16px;height:16px;</style><span></span></a></div><style data-emotion="css vxcmzt">.css-vxcmztdisplay:-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-1q8kglwtext-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:hoverbackground-color:rgba(99, 115, 129, 0.08);@media (hover: none).css-1q8kglw:hoverbackground-color:transparent;.css-1q8kglw.Mui-disabledbackground-color:transparent;color:rgba(145, 159, 171, 0.8);</style><style data-emotion="css f1sec2">.css-f1sec2display:-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-innerborder-style:none;.css-f1sec2.Mui-disabledpointer-events:none;cursor:default;@media print.css-f1sec2-webkit-print-color-adjust:exact;color-adjust:exact;.css-f1sec2:hoverbackground-color:rgba(99, 115, 129, 0.08);@media (hover: none).css-f1sec2:hoverbackground-color:transparent;.css-f1sec2.Mui-disabledbackground-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-bv0lrz-index:1200;.css-bv0lr[role="presentation"] .MuiDrawer-paperAnchorLeftbox-shadow:8px 24px 24px 12px rgba(22, 29, 36, 0.16);.css-bv0lr[role="presentation"] .MuiDrawer-paperAnchorRightbox-shadow:-8px 24px 24px 12px rgba(22, 29, 36, 0.16);</style></div></div></header><div><style data-emotion="css 10klw3m">.css-10klw3mheight:100%;</style><style data-emotion="css w8rns">.css-w8rnsheight:100%;</style><div class="MuiBox-root css-w8rns" id="move_top"><style data-emotion="css 6ipfk0">.css-6ipfk0overflow:hidden;position:relative;background-color:#fff;</style><div class="css-6ipfk0"><style data-emotion="css 17r9e7a">.css-17r9e7apadding-top:120px;@media (min-width:900px).css-17r9e7apadding-bottom:120px;</style><div class="css-17r9e7a"><style data-emotion="css 1m534n9">.css-1m534n9width:100%;margin-left:auto;box-sizing:border-box;margin-right:auto;display:block;padding-left:16px;padding-right:16px;@media (min-width:600px).css-1m534n9padding-left:24px;padding-right:24px;@media (min-width:1200px).css-1m534n9max-width:1200px;</style><div class="MuiContainer-root MuiContainer-maxWidthLg css-1m534n9"><style data-emotion="css 17dd4p5">@media (min-width:0px).css-17dd4p5margin-bottom:80px;@media (min-width:900px).css-17dd4p5margin-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-jw1ye2padding-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-u7kbj0width: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

缓存设置 s-s-r:

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 s-s-r: https://mui.com/guides/server-rendering/

【问题讨论】:

【参考方案1】:

更新: 关于缓存的实际工作原理的文档很差,但这不是错误。 在我运行 codemod 以从 mui4 升级到 mui5 后,通过删除包裹我的代码的 &lt;StyledEngineProvider&gt; 来解决我的问题


我遇到了同样的问题。从情感上看源代码似乎是一个错误,因为捕获的匹配键没有插入到返回的对象上。

一旦键匹配,代码应该对它们进行迭代,而是使用来自cache.inserted 的键执行 forEach。 cache.inserted 将永远是一个空对象,除非您自己处理匹配和插入。

代替:

Object.keys(cache.inserted).forEach(id => 

应该是:

Object.keys(ids).forEach(id => 

你可以check the full code here:

我将在他们的回购中打开一个问题

【讨论】:

谢谢。这无济于事,因为缓存中也缺少样式。 github.com/emotion-js/emotion/blob/…【参考方案2】:

@emotion 团队 (Mateusz) 的回答:

另外说明 - 我不建议使用 css 作为您的密钥。它是 默认的,它可能与其他一些情绪控制的冲突 样式,甚至我们这里的错误都提到键应该不同 比css: https://github.com/emotion-js/emotion/blob/2bac69b6c058d007cfc190e94490c0cb225ca40c/packages/cache/src/index.js#L49-L54

关于您的问题 - 我会首先确保您没有使用 @emotion/core 任何地方,并且您只有一份 @emotion/react 在你的 node_modules 中。

【讨论】:

【参考方案3】:

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

似乎在我从材料 4 升级到 mui 5 后,其中一个 codemod 将我的代码包装在 &lt;StyledEngineProvider&gt; 中以启用样式化组件 s-s-r,并且该提供程序还使用 key:'css' 实例化了一个 EmotionCache,所以它是冲突的使用我添加的自定义emotionCache。一旦我删除了 &lt;StyledEngineProvider&gt; 包装器,所有样式都从 s-s-r 中返回。

【讨论】:

删除 修复了该问题 令人难以置信的文档中没有。

以上是关于带有 Material-UI 的 s-s-r 上的 @emotion/cache 始终为空的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Material-ui 上使用带有 Collapse 的 Menu 作为我的 TransitionComponent?

如何将 Nextjs + styled-components 与 material-ui 集成

带有 Lerna + React + Styled 组件的 s-s-r

在 React 中渲染格式化(未缩小的)HTML(带有 Next.js 的 s-s-r)

NextJS 上的 s-s-r 是如何工作的?

Next 带有静态页面、s-s-r 页面和客户端渲染的 JS Seo