1- import React from 'react' ;
2- import Document , { Head , Main , NextScript } from 'next/document' ;
3- import { ServerStyleSheets } from '@mui/styles' ;
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 '../theme' ;
5+ import createEmotionCache from '../utils/create-emotion-cache' ;
46
5- class MyDocument extends Document {
7+ export default class MyDocument extends Document {
68 render ( ) {
79 return (
8- < html lang = "en" >
10+ < Html lang = "en" >
911 < Head >
10- < meta charSet = "utf-8" />
11- < meta name = "author" content = "Data Driven Forms" />
12- < link rel = "manifest" href = "/manifest.json" />
13- < link rel = "shortcut icon" href = "/favicon.ico" />
14- < link rel = "apple-touch-icon" href = "/192x192.png" > </ link >
15- < meta name = "viewport" content = "minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no" />
1612 { /* PWA primary color */ }
17- < meta name = "theme-color" content = "#430f8f" />
18- < link rel = "preload" as = "style" href = "https://fonts.googleapis.com/css?family=Roboto:300,400,500,700& display = swap " />
19- < link rel = "preload" as = "style" href = "https://fonts.googleapis.com/css?family=Montserrat:700& display = swap " />
20- < link rel = "stylesheet" href = "https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css" />
21- < style
22- dangerouslySetInnerHTML = { {
23- __html : `
24- html {
25- box-sizing: border-box;
26- -webkit-font-smoothing: antialiased;
27- -moz-osx-font-smoothing: grayscale;
28- }
29- *, *::before, *::after {
30- box-sizing: inherit;
31- }
32- strong, b {
33- font-weight: bolder !important;
34- }
35- body {
36- color: rgba(0, 0, 0, 0.87) !important;
37- margin: 0 !important;
38- font-size: 0.875rem !important;
39- font-family: "Roboto", "Helvetica", "Arial", sans-serif !important;
40- font-weight: 400 !important;
41- line-height: 1.43 !important;
42- letter-spacing: 0.01071em !important;
43- background-color: #fafafa !important;
44- }` ,
45- } }
46- />
13+ < meta name = "theme-color" content = { theme . palette . primary . main } />
14+ < link rel = "shortcut icon" href = "/favicon.ico" />
15+ < link rel = "stylesheet" href = "https://fonts.googleapis.com/css?family=Roboto:300,400,500,700& display = swap " />
16+ < meta name = "emotion-insertion-point" content = "" />
17+ { this . props . emotionStyleTags }
4718 </ Head >
4819 < body >
4920 < Main />
5021 < NextScript />
5122 </ body >
52- </ html >
23+ </ Html >
5324 ) ;
5425 }
5526}
5627
28+ // `getInitialProps` belongs to `_document` (instead of `_app`),
29+ // it's compatible with static-site generation (SSG).
5730MyDocument . getInitialProps = async ( ctx ) => {
5831 // Resolution order
5932 //
@@ -77,27 +50,36 @@ MyDocument.getInitialProps = async (ctx) => {
7750 // 3. app.render
7851 // 4. page.render
7952
80- // Render app and page and get the context of the page with collected side effects.
81- const sheets = new ServerStyleSheets ( ) ;
8253 const originalRenderPage = ctx . renderPage ;
8354
55+ // You can consider sharing the same Emotion cache between all the SSR requests to speed up performance.
56+ // However, be aware that it can have global side effects.
57+ const cache = createEmotionCache ( ) ;
58+ const { extractCriticalToChunks } = createEmotionServer ( cache ) ;
59+
8460 ctx . renderPage = ( ) =>
8561 originalRenderPage ( {
86- enhanceApp : ( App ) => ( props ) => sheets . collect ( < App { ...props } /> ) ,
62+ enhanceApp : ( App ) =>
63+ function EnhanceApp ( props ) {
64+ return < App emotionCache = { cache } { ...props } /> ;
65+ } ,
8766 } ) ;
8867
8968 const initialProps = await Document . getInitialProps ( ctx ) ;
69+ // This is important. It prevents Emotion to render invalid HTML.
70+ // See https://github.com/mui/material-ui/issues/26561#issuecomment-855286153
71+ const emotionStyles = extractCriticalToChunks ( initialProps . html ) ;
72+ const emotionStyleTags = emotionStyles . styles . map ( ( style ) => (
73+ < style
74+ data-emotion = { `${ style . key } ${ style . ids . join ( ' ' ) } ` }
75+ key = { style . key }
76+ // eslint-disable-next-line react/no-danger
77+ dangerouslySetInnerHTML = { { __html : style . css } }
78+ />
79+ ) ) ;
9080
9181 return {
9282 ...initialProps ,
93- // Styles fragment is rendered after the app and page rendering finish.
94- styles : [
95- < React . Fragment key = "styles" >
96- { initialProps . styles }
97- { sheets . getStyleElement ( ) }
98- </ React . Fragment > ,
99- ] ,
83+ emotionStyleTags,
10084 } ;
10185} ;
102-
103- export default MyDocument ;
0 commit comments