_document.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import * as React from 'react';
  2. import Document, { Html, Head, Main, NextScript } from 'next/document';
  3. import createEmotionServer from '@emotion/server/create-instance';
  4. import theme from '../src/theme';
  5. import createEmotionCache from '../src/createEmotionCache';
  6. export default class MyDocument extends Document {
  7. render() {
  8. return (
  9. <Html lang="en">
  10. <Head>
  11. {/* PWA primary color */}
  12. <meta name="theme-color" content={theme.palette.primary.main} />
  13. <link rel="shortcut icon" href="/static/favicon.ico" />
  14. <link
  15. rel="stylesheet"
  16. href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
  17. />
  18. {/* Inject MUI styles first to match with the prepend: true configuration. */}
  19. {this.props.emotionStyleTags}
  20. </Head>
  21. <body>
  22. <Main />
  23. <NextScript />
  24. </body>
  25. </Html>
  26. );
  27. }
  28. }
  29. // `getInitialProps` belongs to `_document` (instead of `_app`),
  30. // it's compatible with static-site generation (SSG).
  31. MyDocument.getInitialProps = async (ctx) => {
  32. // Resolution order
  33. //
  34. // On the server:
  35. // 1. app.getInitialProps
  36. // 2. page.getInitialProps
  37. // 3. document.getInitialProps
  38. // 4. app.render
  39. // 5. page.render
  40. // 6. document.render
  41. //
  42. // On the server with error:
  43. // 1. document.getInitialProps
  44. // 2. app.render
  45. // 3. page.render
  46. // 4. document.render
  47. //
  48. // On the client
  49. // 1. app.getInitialProps
  50. // 2. page.getInitialProps
  51. // 3. app.render
  52. // 4. page.render
  53. const originalRenderPage = ctx.renderPage;
  54. // You can consider sharing the same Emotion cache between all the SSR requests to speed up performance.
  55. // However, be aware that it can have global side effects.
  56. const cache = createEmotionCache();
  57. const { extractCriticalToChunks } = createEmotionServer(cache);
  58. ctx.renderPage = () =>
  59. originalRenderPage({
  60. enhanceApp: (App) =>
  61. function EnhanceApp(props) {
  62. return <App emotionCache={cache} {...props} />;
  63. },
  64. });
  65. const initialProps = await Document.getInitialProps(ctx);
  66. // This is important. It prevents Emotion to render invalid HTML.
  67. // See https://github.com/mui/material-ui/issues/26561#issuecomment-855286153
  68. const emotionStyles = extractCriticalToChunks(initialProps.html);
  69. const emotionStyleTags = emotionStyles.styles.map((style) => (
  70. <style
  71. data-emotion={`${style.key} ${style.ids.join(' ')}`}
  72. key={style.key}
  73. // eslint-disable-next-line react/no-danger
  74. dangerouslySetInnerHTML={{ __html: style.css }}
  75. />
  76. ));
  77. return {
  78. ...initialProps,
  79. emotionStyleTags,
  80. };
  81. };