title: Server-side rendering broken after upgrading to MUI 5 (with Next.js)
body: <p>I migrated my <a href="https://en.wikipedia.org/wiki/Server-side_scripting#Server-side_rendering" rel="nofollow noreferrer">server-side rendering</a> (SSR) working app to version 5 of MUI. I followed the <a href="https://mui.com/guides/migration-v4/" rel="nofollow noreferrer">official procedure</a>, but when I disabled JavaScript, I received a raw HTML page (without CSS). You can see it <a href="https://preprod.weally.org" rel="nofollow noreferrer">here</a> (sorry if it's down; I’m redeploying often to test).</p>
  <ol>
  <li>run codemod (v5.0.0/preset-safe and link-underline-hover)</li>
  <li>changed the makeStyles calls to use <a href="https://mui.com/guides/migration-v4/#2-use-tss-react" rel="nofollow noreferrer">tss-react</a></li>
  <li>modified my <em>_app</em> and <em>_document</em> files according to the <a href="https://github.com/mui/material-ui/tree/master/examples/nextjs" rel="nofollow noreferrer">MUI example with Next.js</a></li>
  </ol>
  <p>I launched the official <a href="https://github.com/mui/material-ui/tree/master/examples/nextjs" rel="nofollow noreferrer">SSR Next.js implementation</a>. It showed it doesn't work either.</p>
  <p><a href="https://i.stack.imgur.com/oJXIo.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/oJXIo.png" alt="Server-side rendering with JavaScript disabled" /></a></p>
  <p>For more details, here are the key files in my project:</p>
  <p><strong>_app.js</strong></p>
  <pre class="lang-jsx prettyprint-override"><code>import * as React from 'react';
  import Head from 'next/head';
  import {ThemeProvider} from '@mui/material/styles';
  import CssBaseline from '@mui/material/CssBaseline';
  import {CacheProvider} from '@emotion/react';
  import theme from '../components/theme';
  import createEmotionCache from &quot;../lib/createEmotionCache&quot;;
  import {StyledEngineProvider} from '@mui/material/styles';
  import {ApolloProvider} from &quot;@apollo/client&quot;;
  import {SessionProvider} from &quot;next-auth/react&quot;
  import {appWithTranslation} from &quot;next-i18next&quot;;
  import {useApollo} from &quot;../apollo/client&quot;;
  // Client-side cache, shared for the whole session of the user in the browser.
  const clientSideEmotionCache = createEmotionCache();
  
  //followed example: https://github.com/mui/material-ui/tree/master/examples/nextjs
  function App(props) {
      const {Component, emotionCache = clientSideEmotionCache, pageProps} = props;
      const apolloClient = useApollo(pageProps)
  
      return (
          &lt;CacheProvider value={emotionCache}&gt;
              &lt;StyledEngineProvider injectFirst&gt;
                  &lt;ApolloProvider client={apolloClient}&gt;
                      &lt;SessionProvider session={pageProps.session}&gt;
                          &lt;Head&gt;
                              &lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1, width=device-width&quot;/&gt;
  
                              &lt;title&gt;WeAlly&lt;/title&gt;
                              &lt;meta name=&quot;viewport&quot; content=&quot;minimum-scale=1, initial-scale=1, width=device-width&quot;/&gt;
                              &lt;link rel=&quot;apple-touch-icon&quot; sizes=&quot;180x180&quot; href=&quot;/images/apple-touch-icon.png&quot;/&gt;
                              &lt;link rel=&quot;icon&quot; type=&quot;image/png&quot; sizes=&quot;32x32&quot; href=&quot;/images/favicon-32x32.png&quot;/&gt;
                              &lt;link rel=&quot;icon&quot; type=&quot;image/png&quot; sizes=&quot;16x16&quot; href=&quot;/images/favicon-16x16.png&quot;/&gt;
                              &lt;link rel=&quot;manifest&quot; href=&quot;/images/site.webmanifest&quot;/&gt;
                          &lt;/Head&gt;
  
                          &lt;ThemeProvider theme={theme}&gt;
                              {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
                              &lt;CssBaseline/&gt;
                              &lt;Component {...pageProps} /&gt;
                          &lt;/ThemeProvider&gt;
                      &lt;/SessionProvider&gt;
                  &lt;/ApolloProvider&gt;
              &lt;/StyledEngineProvider&gt;
          &lt;/CacheProvider&gt;
      );
  }
  
  
  export default appWithTranslation(App);
  </code></pre>
  <p><strong>_document.js</strong></p>
  <pre class="lang-jsx prettyprint-override"><code>import * as React from 'react';
  import Document, { Html, Head, Main, NextScript } from 'next/document';
  import createEmotionServer from '@emotion/server/create-instance';
  import theme from '../components/theme';
  import createEmotionCache from &quot;../lib/createEmotionCache&quot;;
  
  export default class MyDocument extends Document {
      render() {
          return (
              &lt;Html lang=&quot;en&quot;&gt;
                  &lt;Head&gt;
                      {/* PWA primary color */}
                      &lt;meta name=&quot;theme-color&quot; content={theme.palette.primary.main} /&gt;
                      &lt;link rel=&quot;shortcut icon&quot; href=&quot;/static/favicon.ico&quot; /&gt;
                      &lt;link
                          rel=&quot;stylesheet&quot;
                          href=&quot;https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&amp;display=swap&quot;
                      /&gt;
                      &lt;link rel=&quot;preconnect&quot; href=&quot;https://fonts.googleapis.com&quot;/&gt;
                      &lt;link rel=&quot;preconnect&quot; href=&quot;https://fonts.gstatic.com&quot;/&gt;
                      &lt;link href=&quot;https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;700&amp;display=swap&quot;
                            rel=&quot;stylesheet&quot;/&gt;
  
                      &lt;link
                          href=&quot;https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300;0,400;0,600;1,400&amp;display=swap&quot;
                          rel=&quot;stylesheet&quot;/&gt;
  
                      &lt;link rel=&quot;stylesheet&quot;
                            href=&quot;https://fonts.googleapis.com/icon?family=Material+Icons&amp;display=swap&quot;
                            media=&quot;screen&quot;/&gt;
                      {/* Inject MUI styles first to match with the prepend: true configuration. */}
                      {this.props.emotionStyleTags}
                  &lt;/Head&gt;
                  &lt;body&gt;
                  &lt;Main /&gt;
                  &lt;NextScript /&gt;
                  &lt;/body&gt;
              &lt;/Html&gt;
          );
      }
  }
  
  // `getInitialProps` belongs to `_document` (instead of `_app`),
  // it's compatible with static-site generation (SSG).
  MyDocument.getInitialProps = async (ctx) =&gt; {
      const originalRenderPage = ctx.renderPage;
  
      // You can consider sharing the same emotion cache between all the SSR requests to speed up performance.
      // However, be aware that it can have global side effects.
      const cache = createEmotionCache();
      const { extractCriticalToChunks } = createEmotionServer(cache);
  
      ctx.renderPage = () =&gt;
          originalRenderPage({
              enhanceApp: (App) =&gt;
                  (function EnhanceApp(props) {
                      // console.log( 'enhancing app with cache: ', cache )
                      return &lt;App emotionCache={cache} {...props} /&gt;;
                  }),
          });
  
      const initialProps = await Document.getInitialProps(ctx);
      // This is important. It prevents emotion from rendering invalid HTML.
      // See https://github.com/mui/material-ui/issues/26561#issuecomment-855286153
      const emotionStyles = extractCriticalToChunks(initialProps.html);
      // console.log('emotion style count: ', emotionStyles.styles.length)
      const emotionStyleTags = emotionStyles.styles.map((style) =&gt; (
          &lt;style
              data-emotion={`${style.key} ${style.ids.join(' ')}`}
              key={style.key}
              // eslint-disable-next-line react/no-danger
              dangerouslySetInnerHTML={{ __html: style.css }}
          /&gt;
      ));
  
      return {
          ...initialProps,
          emotionStyleTags,
      };
  };
  
  **package.json**
  
  {
    &quot;name&quot;: &quot;we-ally-org&quot;,
    &quot;version&quot;: &quot;1.0.0&quot;,
    &quot;scripts&quot;: {
      &quot;dev&quot;: &quot;next&quot;,
      &quot;back&quot;: &quot;node ./server/starter.js&quot;,
      &quot;build&quot;: &quot;next build&quot;,
      &quot;start&quot;: &quot;next start&quot;
    },
    &quot;dependencies&quot;: {
      &quot;@apollo/client&quot;: &quot;^3.4.17&quot;,
      &quot;@emotion/react&quot;: &quot;^11.8.2&quot;,
      &quot;@emotion/styled&quot;: &quot;^11.8.1&quot;,
      &quot;@google/maps&quot;: &quot;^1.1.3&quot;,
      &quot;@hapi/iron&quot;: &quot;6.0.0&quot;,
      &quot;@mui/icons-material&quot;: &quot;^5.5.1&quot;,
      &quot;@mui/material&quot;: &quot;^5.5.2&quot;,
      &quot;@mui/styles&quot;: &quot;^5.5.1&quot;,
      &quot;@next-auth/mongodb-adapter&quot;: &quot;^1.0.3&quot;,
      &quot;@next/bundle-analyzer&quot;: &quot;^11.1.0&quot;,
      &quot;@prisma/client&quot;: &quot;2.16.1&quot;,
      &quot;apollo-server-micro&quot;: &quot;^3.5.0&quot;,
      &quot;axios&quot;: &quot;^0.21.1&quot;,
      &quot;body-parser&quot;: &quot;^1.19.0&quot;,
      &quot;classnames&quot;: &quot;^2.3.1&quot;,
      &quot;cookie&quot;: &quot;^0.4.1&quot;,
      &quot;cors&quot;: &quot;^2.8.5&quot;,
      &quot;deepmerge&quot;: &quot;4.2.2&quot;,
      &quot;ejs&quot;: &quot;^3.1.6&quot;,
      &quot;express-graphql&quot;: &quot;^0.12.0&quot;,
      &quot;express-jwt&quot;: &quot;^6.0.0&quot;,
      &quot;express-session&quot;: &quot;^1.17.2&quot;,
      &quot;google-map-react&quot;: &quot;^2.1.9&quot;,
      &quot;graphql&quot;: &quot;^15.5.1&quot;,
      &quot;graphql-tools&quot;: &quot;^8.1.0&quot;,
      &quot;graphql-ws&quot;: &quot;^5.4.0&quot;,
      &quot;http-proxy&quot;: &quot;^1.18.1&quot;,
      &quot;image-type&quot;: &quot;^4.1.0&quot;,
      &quot;jodit-react&quot;: &quot;^1.1.1&quot;,
      &quot;jsonwebtoken&quot;: &quot;^8.5.1&quot;,
      &quot;linkify-react&quot;: &quot;^3.0.4&quot;,
      &quot;linkifyjs&quot;: &quot;^3.0.5&quot;,
      &quot;lodash&quot;: &quot;^4.17.21&quot;,
      &quot;micro&quot;: &quot;^9.3.4&quot;,
      &quot;moment&quot;: &quot;^2.29.1&quot;,
      &quot;mongodb&quot;: &quot;^4.4.1&quot;,
      &quot;next&quot;: &quot;12&quot;,
      &quot;next-auth&quot;: &quot;^4.3.1&quot;,
      &quot;next-compose-plugins&quot;: &quot;^2.2.1&quot;,
      &quot;next-i18next&quot;: &quot;^8.5.1&quot;,
      &quot;node-fetch&quot;: &quot;^3.0.0&quot;,
      &quot;passport&quot;: &quot;^0.4.1&quot;,
      &quot;passport-facebook&quot;: &quot;^3.0.0&quot;,
      &quot;pino&quot;: &quot;^6.11.3&quot;,
      &quot;prop-types&quot;: &quot;^15.6.2&quot;,
      &quot;react&quot;: &quot;^17.0.2&quot;,
      &quot;react-dom&quot;: &quot;^17.0.2&quot;,
      &quot;react-ga&quot;: &quot;^3.3.0&quot;,
      &quot;react-image-gallery&quot;: &quot;^1.2.7&quot;,
      &quot;react-moment&quot;: &quot;^1.1.1&quot;,
      &quot;react-player&quot;: &quot;^2.9.0&quot;,
      &quot;react-share&quot;: &quot;^4.4.0&quot;,
      &quot;react-use&quot;: &quot;^17.2.4&quot;,
      &quot;sanitize-html&quot;: &quot;^2.4.0&quot;,
      &quot;subscriptions-transport-ws&quot;: &quot;^0.9.19&quot;,
      &quot;tss-react&quot;: &quot;^3.6.0&quot;
    },
    &quot;license&quot;: &quot;MIT&quot;,
    &quot;devDependencies&quot;: {
      &quot;@babel/core&quot;: &quot;^7.15.5&quot;,
      &quot;@emotion/server&quot;: &quot;^11.4.0&quot;,
      &quot;babel-plugin-styled-components&quot;: &quot;^2.0.6&quot;,
      &quot;eslint&quot;: &quot;8.11.0&quot;,
      &quot;eslint-config-next&quot;: &quot;12.1.0&quot;
    }
  }
  
  </code></pre>
  <p>Also, a dependency library was broken: <strong>react-image-gallery</strong> <a href="http://localhost/request/6239a059691bb0c4af2657e5/detail" rel="nofollow noreferrer">displays incorrectly</a> since the upgrade, but I still didn't dig into that.</p>