Skip to content

Commit e68b78c

Browse files
committed
fix(ssr): add emotion cache
1 parent 1d5213e commit e68b78c

File tree

5 files changed

+239
-10
lines changed

5 files changed

+239
-10
lines changed

package-lock.json

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

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
"build-storybook": "storybook build"
1919
},
2020
"dependencies": {
21+
"@emotion/cache": "^11.14.0",
2122
"@emotion/react": "11.14.0",
23+
"@emotion/server": "^11.11.0",
2224
"@emotion/styled": "11.14.1",
2325
"@faker-js/faker": "9.8.0",
2426
"@fontsource/roboto": "5.2.6",

src/components/theme/init-color-scheme-script.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
"use client";
2-
31
import InitColorSchemeScriptMui from "@mui/material/InitColorSchemeScript";
42

53
function InitColorSchemeScript() {

src/components/theme/registry.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"use client";
2+
3+
import React, { useState } from "react";
4+
import { useServerInsertedHTML } from "next/navigation";
5+
import { CacheProvider } from "@emotion/react";
6+
import createCache from "@emotion/cache";
7+
8+
export default function StyledJsxRegistry({
9+
children,
10+
}: {
11+
children: React.ReactNode;
12+
}) {
13+
const [{ cache, flush }] = useState(() => {
14+
const cache = createCache({ key: "mui" });
15+
cache.compat = true;
16+
const prevInsert = cache.insert;
17+
let inserted: string[] = [];
18+
cache.insert = (...args) => {
19+
const serialized = args[1];
20+
if (cache.inserted[serialized.name] === undefined) {
21+
inserted.push(serialized.name);
22+
}
23+
return prevInsert(...args);
24+
};
25+
const flush = () => {
26+
const prevInserted = inserted;
27+
inserted = [];
28+
return prevInserted;
29+
};
30+
return { cache, flush };
31+
});
32+
33+
useServerInsertedHTML(() => {
34+
const names = flush();
35+
if (names.length === 0) {
36+
return null;
37+
}
38+
let styles = "";
39+
for (const name of names) {
40+
styles += cache.inserted[name];
41+
}
42+
return (
43+
<style
44+
key={cache.key}
45+
data-emotion={`${cache.key} ${names.join(" ")}`}
46+
dangerouslySetInnerHTML={{
47+
__html: styles,
48+
}}
49+
/>
50+
);
51+
});
52+
53+
return <CacheProvider value={cache}>{children}</CacheProvider>;
54+
}

src/components/theme/theme-provider.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
ThemeProvider as MuiThemeProvider,
66
} from "@mui/material/styles";
77
import { useMemo, PropsWithChildren } from "react";
8+
import StyledJsxRegistry from "./registry";
89

910
function ThemeProvider(props: PropsWithChildren<{}>) {
1011
const theme = useMemo(
@@ -18,7 +19,11 @@ function ThemeProvider(props: PropsWithChildren<{}>) {
1819
[]
1920
);
2021

21-
return <MuiThemeProvider theme={theme}>{props.children}</MuiThemeProvider>;
22+
return (
23+
<StyledJsxRegistry>
24+
<MuiThemeProvider theme={theme}>{props.children}</MuiThemeProvider>
25+
</StyledJsxRegistry>
26+
);
2227
}
2328

2429
export default ThemeProvider;

0 commit comments

Comments
 (0)