diff --git a/apps/dev/package.json b/apps/dev/package.json index e939d805ef8..f034bb689ab 100644 --- a/apps/dev/package.json +++ b/apps/dev/package.json @@ -18,6 +18,10 @@ "webpack": "^5" }, "dependencies": { + "@emotion/react": "11.8.1", + "@emotion/server": "11.4.0", + "@emotion/styled": "11.8.1", + "@mui/material": "5.5.0", "next": "12.1.0", "react": "17.0.2", "react-dom": "17.0.2" diff --git a/apps/dev/src/pages/_app.page.tsx b/apps/dev/src/pages/_app.page.tsx index 6b39d6bf134..a09f1349fd1 100644 --- a/apps/dev/src/pages/_app.page.tsx +++ b/apps/dev/src/pages/_app.page.tsx @@ -1,9 +1,30 @@ -import { VFC } from "react"; +import { CacheProvider, EmotionCache, ThemeProvider } from "@emotion/react"; +import CssBaseline from "@mui/material/CssBaseline"; import type { AppProps } from "next/app"; +import { VFC } from "react"; import "../../styles/globals.css"; +import { theme } from "../theme"; +import { createEmotionCache } from "../util/createEmotionCache"; + +const clientSideEmotionCache = createEmotionCache(); + +type MyAppProps = { + emotionCache?: EmotionCache; +} & AppProps; -const MyApp: VFC = ({ Component, pageProps }) => { - return ; +const MyApp: VFC = ({ + Component, + pageProps, + emotionCache = clientSideEmotionCache, +}) => { + return ( + + + + + + + ); }; export default MyApp; diff --git a/apps/dev/src/pages/_document.page.tsx b/apps/dev/src/pages/_document.page.tsx new file mode 100644 index 00000000000..fd8d3e3ba1d --- /dev/null +++ b/apps/dev/src/pages/_document.page.tsx @@ -0,0 +1,103 @@ +import React from "react"; +import Document, { + Html, + Head, + Main, + NextScript, + DocumentContext, +} from "next/document"; +import createEmotionServer from "@emotion/server/create-instance"; +import { createEmotionCache } from "../util/createEmotionCache"; + +class MyDocument extends Document { + static async getInitialProps(ctx: DocumentContext) { + const initialProps = await Document.getInitialProps(ctx); + return { ...initialProps }; + } + + render() { + return ( + + + {/** @todo meta */} + + + {/** @todo add icons */} + + +
+ + + + ); + } +} + +// `getInitialProps` belongs to `_document` (instead of `_app`), +// it's compatible with static-site generation (SSG). +MyDocument.getInitialProps = async (ctx) => { + // Resolution order + // + // On the server: + // 1. app.getInitialProps + // 2. page.getInitialProps + // 3. document.getInitialProps + // 4. app.render + // 5. page.render + // 6. document.render + // + // On the server with error: + // 1. document.getInitialProps + // 2. app.render + // 3. page.render + // 4. document.render + // + // On the client + // 1. app.getInitialProps + // 2. page.getInitialProps + // 3. app.render + // 4. page.render + + 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 = () => + originalRenderPage({ + enhanceApp: (App: any) => + // eslint-disable-next-line react/function-component-definition + function EnhanceApp(props) { + return ; + }, + }); + + const initialProps = await Document.getInitialProps(ctx); + // This is important. It prevents emotion to render invalid HTML. + // See https://github.com/mui-org/material-ui/issues/26561#issuecomment-855286153 + const emotionStyles = extractCriticalToChunks(initialProps.html); + const emotionStyleTags = emotionStyles.styles.map((style) => ( +