@emotion/cache@11.6.0
has deprecated the option prepend
in favor of insertionPoint
. link
When I tested insertionPoint
option in a Next.js app with the mantine UI library the behavior was not consistent between development
and production
mode.
In development
everything seemed fine. However in production
mantine style where prepend to the head. Since I use a global.css
stylesheet to normalize styles it was loaded after the mantine style. Hence my normalization style where overriding mantine styles and the button was transparent in production.
Eventually, after many trials I was able to make it work. The issue seems related to the hydration process.
The tipping point of the solution was to call createEmotionCache
inside the rendering context of _app.tsx
.
export default function App(props: AppProps) {
const { Component, pageProps } = props;
// get the cache instance in the context of _app rendering
// Note: if the cache instance is retrieved outside the _app rendering context the insertionPoint is propery identified
const cache = emCache();
return (
<>
<Head>
// lib/emotionCache.ts
import { createEmotionCache, EmotionCache } from "@mantine/core";
import { last } from "remeda";
//cache instance
let cache: EmotionCache | undefined;
const getInsertionPoint = () =>
typeof document !== "undefined" && process.env.NODE_ENV === "production"
? last([
...(document
.querySelector("head")
?.querySelectorAll<HTMLElement>(`script`) ?? []),
])
: undefined;
const creatCache = () =>
createEmotionCache({
key: "mantine",
insertionPoint: getInsertionPoint(),
});
export const emCache = () => {
console.log("= insertionPoint element = ", getInsertionPoint());
// we create the cache instance only once so it's consistent between SSR and client side.
if (!cache) {
cache = creatCache();
}
return cache;
};
I did not spend much time testing this implementation and maybe I am missing something. Any help, feedback will be appreciated.