Skip to content

Commit 300b8ad

Browse files
committed
refactor: use mui nextjs integration
1 parent 68c3884 commit 300b8ad

File tree

4 files changed

+73
-114
lines changed

4 files changed

+73
-114
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"@mui/icons-material": "6.1.6",
4545
"@mui/lab": "6.0.0-beta.14",
4646
"@mui/material": "6.1.6",
47+
"@mui/material-nextjs": "^6.1.9",
4748
"@mui/styles": "6.1.6",
4849
"@next/eslint-plugin-next": "15.0.3",
4950
"@next/mdx": "15.0.3",

pnpm-lock.yaml

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/pages/_app.tsx

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
1-
import { useEffect, useMemo } from "react";
1+
import { useMemo } from "react";
22

33
import { setBaseUrl as setASBaseUrl } from "@squonk/account-server-client";
44
import { setBaseUrl as setDMBaseUrl } from "@squonk/data-manager-client";
55

66
import { UserProvider } from "@auth0/nextjs-auth0/client";
7-
import { type EmotionCache } from "@emotion/cache";
8-
import { CacheProvider } from "@emotion/react";
7+
import {
8+
AppCacheProvider,
9+
type EmotionCacheProviderProps,
10+
} from "@mui/material-nextjs/v15-pagesRouter";
911
import { HydrationBoundary, QueryClient, QueryClientProvider } from "@tanstack/react-query";
1012
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
1113
import { enableMapSet } from "immer";
1214
import { type AppProps } from "next/app";
13-
import Head from "next/head";
1415
import { SnackbarProvider } from "notistack";
1516

1617
import { ThemeProviders } from "../components/app/ThemeProviders";
1718
import { TopLevelHooks } from "../components/app/TopLevelHooks";
1819
import { AS_API_URL, DM_API_URL } from "../constants/proxies";
1920
import { MDXComponentProvider } from "../context/MDXComponentProvider";
20-
import createEmotionCache from "../utils/next/createEmotionCache";
2121

2222
import "../styles/globalStyles.scss";
2323

24-
const clientSideEmotionCache = createEmotionCache();
25-
2624
setDMBaseUrl(DM_API_URL);
2725
setASBaseUrl(AS_API_URL);
2826

@@ -31,35 +29,22 @@ enableMapSet();
3129
// Adjust template for MUI given at
3230
// https://github.com/mui/material-ui/blob/master/examples/nextjs-with-typescript/pages/_app.tsx
3331

34-
type CustomAppProps = AppProps & {
35-
emotionCache?: EmotionCache;
36-
pageProps: { dehydratedState?: unknown };
37-
};
32+
type CustomAppProps = AppProps &
33+
EmotionCacheProviderProps & {
34+
pageProps: { dehydratedState?: unknown };
35+
};
3836

39-
const App = ({ Component, pageProps, emotionCache = clientSideEmotionCache }: CustomAppProps) => {
37+
const App = ({ Component, pageProps }: CustomAppProps) => {
4038
// React-Query
4139
const queryClient = useMemo(() => new QueryClient(), []);
4240

43-
// Material UI for SSR
44-
useEffect(() => {
45-
// Remove the server-side injected CSS.
46-
const jssStyles = document.querySelector("#jss-server-side");
47-
if (jssStyles) {
48-
// eslint-disable-next-line unicorn/prefer-dom-node-remove
49-
jssStyles.parentElement?.removeChild(jssStyles);
50-
}
51-
}, []);
52-
5341
// Vercel specific code is only imported if needed
5442
// if (process.env.NEXT_PUBLIC_VERCEL_URL) {
5543
// import("../utils/next/vercelRedirect").then(({ vercelRedirect }) => vercelRedirect());
5644
// }
5745

5846
return (
59-
<CacheProvider value={emotionCache}>
60-
<Head>
61-
<meta content="minimum-scale=1, initial-scale=1, width=device-width" name="viewport" />
62-
</Head>
47+
<AppCacheProvider {...pageProps}>
6348
<ThemeProviders>
6449
<UserProvider
6550
loginUrl={`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/auth/login`}
@@ -79,7 +64,7 @@ const App = ({ Component, pageProps, emotionCache = clientSideEmotionCache }: Cu
7964
</QueryClientProvider>
8065
</UserProvider>
8166
</ThemeProviders>
82-
</CacheProvider>
67+
</AppCacheProvider>
8368
);
8469
};
8570

src/pages/_document.tsx

Lines changed: 28 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,30 @@
1-
import generateThemes from "@squonk/mui-theme";
2-
3-
import createEmotionServer from "@emotion/server/create-instance";
4-
import Document, { Head, Html, Main, NextScript } from "next/document";
5-
6-
import createEmotionCache from "../utils/next/createEmotionCache";
7-
8-
const { lightTheme } = generateThemes();
9-
10-
// Adapted from
11-
// https://github.com/mui/material-ui/blob/master/examples/nextjs-with-typescript/pages/_document.tsx
12-
13-
export default class MyDocument extends Document {
14-
render() {
15-
return (
16-
<Html lang="en">
17-
<Head>
18-
{/* PWA primary color */}
19-
<meta content={lightTheme.palette.primary.main} name="theme-color" />
20-
{/* Inject MUI styles first to match with the prepend: true configuration. */}
21-
{(this.props as any).emotionStyleTags}
22-
</Head>
23-
<body>
24-
<Main />
25-
<NextScript />
26-
</body>
27-
</Html>
28-
);
29-
}
30-
}
31-
32-
// `getInitialProps` belongs to `_document` (instead of `_app`),
33-
// it's compatible with static-site generation (SSG).
34-
MyDocument.getInitialProps = async (ctx) => {
35-
// Resolution order
36-
//
37-
// On the server:
38-
// 1. app.getInitialProps
39-
// 2. page.getInitialProps
40-
// 3. document.getInitialProps
41-
// 4. app.render
42-
// 5. page.render
43-
// 6. document.render
44-
//
45-
// On the server with error:
46-
// 1. document.getInitialProps
47-
// 2. app.render
48-
// 3. page.render
49-
// 4. document.render
50-
//
51-
// On the client
52-
// 1. app.getInitialProps
53-
// 2. page.getInitialProps
54-
// 3. app.render
55-
// 4. page.render
56-
57-
const originalRenderPage = ctx.renderPage;
58-
59-
// You can consider sharing the same emotion cache between all the SSR requests to speed up performance.
60-
// However, be aware that it can have global side effects.
61-
const cache = createEmotionCache();
62-
const { extractCriticalToChunks } = createEmotionServer(cache);
63-
64-
ctx.renderPage = () =>
65-
originalRenderPage({
66-
enhanceApp: (App: any) =>
67-
function EnhanceApp(props) {
68-
return <App emotionCache={cache} {...props} />;
69-
},
70-
});
71-
72-
const initialProps = await Document.getInitialProps(ctx);
73-
// This is important. It prevents emotion to render invalid HTML.
74-
// See https://github.com/mui/material-ui/issues/26561#issuecomment-855286153
75-
const emotionStyles = extractCriticalToChunks(initialProps.html);
76-
const emotionStyleTags = emotionStyles.styles.map((style) => (
77-
<style
78-
// eslint-disable-next-line react/no-danger
79-
dangerouslySetInnerHTML={{ __html: style.css }}
80-
data-emotion={`${style.key} ${style.ids.join(" ")}`}
81-
key={style.key}
82-
/>
83-
));
1+
import {
2+
documentGetInitialProps,
3+
DocumentHeadTags,
4+
type DocumentHeadTagsProps,
5+
} from "@mui/material-nextjs/v15-pagesRouter";
6+
import { type DocumentContext, Head, Html, Main, NextScript } from "next/document";
7+
8+
type DocumentProps = DocumentHeadTagsProps;
9+
10+
const MyDocument = (props: DocumentProps) => {
11+
return (
12+
<Html lang="en">
13+
<Head>
14+
<meta content="minimum-scale=1, initial-scale=1, width=device-width" name="viewport" />
15+
<DocumentHeadTags {...props} />
16+
</Head>
17+
<body>
18+
<Main />
19+
<NextScript />
20+
</body>
21+
</Html>
22+
);
23+
};
8424

85-
return {
86-
...initialProps,
87-
emotionStyleTags,
88-
};
25+
MyDocument.getInitialProps = async (ctx: DocumentContext) => {
26+
const finalProps = await documentGetInitialProps(ctx);
27+
return finalProps;
8928
};
29+
30+
export default MyDocument;

0 commit comments

Comments
 (0)