Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[examples] Improve integration examples with Next.js #27331

Merged
merged 12 commits into from
Jul 28, 2021
16 changes: 12 additions & 4 deletions docs/pages/_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import PropTypes from 'prop-types';
import acceptLanguage from 'accept-language';
import { create } from 'jss';
import jssRtl from 'jss-rtl';
import { CacheProvider } from '@emotion/react';
import { useRouter } from 'next/router';
import { StylesProvider, jssPreset } from '@material-ui/styles';
import { StyledEngineProvider } from '@material-ui/core/styles';
Expand All @@ -22,6 +23,10 @@ import { pathnameToLanguage, getCookie } from 'docs/src/modules/utils/helpers';
import { ACTION_TYPES, CODE_VARIANTS, LANGUAGES } from 'docs/src/modules/constants';
import { useUserLanguage } from 'docs/src/modules/utils/i18n';
import DocsStyledEngineProvider from 'docs/src/modules/utils/StyledEngineProvider';
import createEmotionCache from 'docs/src/createEmotionCache';

// Client-side cache, shared for the whole session of the user in the browser.
const clientSideEmotionCache = createEmotionCache();

// Configure JSS
const jss = create({
Expand Down Expand Up @@ -353,17 +358,20 @@ AppWrapper.propTypes = {
};

export default function MyApp(props) {
const { Component, pageProps } = props;
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;

return (
<AppWrapper pageProps={pageProps}>
<Component {...pageProps} />
</AppWrapper>
<CacheProvider value={emotionCache}>
<AppWrapper pageProps={pageProps}>
<Component {...pageProps} />
</AppWrapper>
</CacheProvider>
);
}

MyApp.propTypes = {
Component: PropTypes.elementType.isRequired,
emotionCache: PropTypes.object,
pageProps: PropTypes.object.isRequired,
};

Expand Down
20 changes: 4 additions & 16 deletions docs/pages/_document.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,10 @@ import { ServerStyleSheets } from '@material-ui/styles';
import { createTheme } from '@material-ui/core/styles';
import { ServerStyleSheet } from 'styled-components';
import createEmotionServer from '@emotion/server/create-instance';
import { CacheProvider } from '@emotion/react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import { LANGUAGES_SSR } from 'docs/src/modules/constants';
import { pathnameToLanguage } from 'docs/src/modules/utils/helpers';
import createCache from '@emotion/cache';

function getCache() {
const cache = createCache({ key: 'css', prepend: true });
cache.compat = true;
return cache;
}
import createEmotionCache from 'docs/src/createEmotionCache';

const defaultTheme = createTheme();

Expand Down Expand Up @@ -129,20 +122,15 @@ MyDocument.getInitialProps = async (ctx) => {
const styledComponentsSheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;

const cache = getCache();
const cache = createEmotionCache();
const { extractCriticalToChunks } = createEmotionServer(cache);

try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
styledComponentsSheet.collectStyles(materialSheets.collect(<App {...props} />)),
// Take precedence over the CacheProvider in our custom _app.js
enhanceComponent: (Component) => (props) =>
(
<CacheProvider value={cache}>
<Component {...props} />
</CacheProvider>
styledComponentsSheet.collectStyles(
materialSheets.collect(<App emotionCache={cache} {...props} />),
),
});

Expand Down
5 changes: 5 additions & 0 deletions docs/src/createEmotionCache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import createCache from '@emotion/cache';

export default function createEmotionCache() {
return createCache({ key: 'css', prepend: true });
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import type { AppProps } from 'next/app';
import Head from 'next/head';
import theme from '../src/theme';

export default function MyApp({ Component, pageProps }: AppProps) {
export default function MyApp(props: AppProps) {
const { Component, pageProps } = props;
return (
<React.Fragment>
<Head>
Expand Down
18 changes: 11 additions & 7 deletions examples/nextjs-with-typescript/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@ import Head from 'next/head';
import { AppProps } from 'next/app';
import { ThemeProvider } from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
import { CacheProvider, EmotionCache } from '@emotion/react';
import theme from '../src/theme';
import createEmotionCache from '../src/createEmotionCache';

const cache = createCache({ key: 'css', prepend: true });
cache.compat = true;
// Client-side cache, shared for the whole session of the user in the browser.
const clientSideEmotionCache = createEmotionCache();

export default function MyApp(props: AppProps) {
const { Component, pageProps } = props;
interface MyAppProps extends AppProps {
emotionCache?: EmotionCache;
}

export default function MyApp(props: MyAppProps) {
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;
return (
<CacheProvider value={cache}>
<CacheProvider value={emotionCache}>
<Head>
<title>My page</title>
<meta name="viewport" content="initial-scale=1, width=device-width" />
Expand Down
23 changes: 7 additions & 16 deletions examples/nextjs-with-typescript/pages/_document.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import * as React from 'react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import createEmotionServer from '@emotion/server/create-instance';
import theme from '../src/theme';

function getCache() {
const cache = createCache({ key: 'css', prepend: true });
cache.compat = true;
return cache;
}
import createEmotionCache from '../src/createEmotionCache';

export default class MyDocument extends Document {
render() {
Expand Down Expand Up @@ -59,21 +52,19 @@ MyDocument.getInitialProps = async (ctx) => {

const originalRenderPage = ctx.renderPage;

const cache = getCache();
// 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({
// Take precedence over the CacheProvider in our custom _app.js
enhanceComponent: (Component) => (props) =>
(
<CacheProvider value={cache}>
<Component {...props} />
</CacheProvider>
),
enhanceApp: (App: any) => (props) => <App emotionCache={cache} {...props} />,
});

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) => (
<style
Expand Down
5 changes: 5 additions & 0 deletions examples/nextjs-with-typescript/src/createEmotionCache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import createCache from '@emotion/cache';

export default function createEmotionCache() {
return createCache({ key: 'css' });
}
12 changes: 7 additions & 5 deletions examples/nextjs/pages/_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import Head from 'next/head';
import { ThemeProvider } from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
import theme from '../src/theme';
import createEmotionCache from '../src/createEmotionCache';

const cache = createCache({ key: 'css' });
cache.compat = true;
// Client-side cache, shared for the whole session of the user in the browser.
const clientSideEmotionCache = createEmotionCache();

export default function MyApp(props) {
const { Component, pageProps } = props;
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;

return (
<CacheProvider value={cache}>
<CacheProvider value={emotionCache}>
<Head>
<title>My page</title>
<meta name="viewport" content="initial-scale=1, width=device-width" />
Expand All @@ -29,5 +30,6 @@ export default function MyApp(props) {

MyApp.propTypes = {
Component: PropTypes.elementType.isRequired,
emotionCache: PropTypes.object,
pageProps: PropTypes.object.isRequired,
};
23 changes: 7 additions & 16 deletions examples/nextjs/pages/_document.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import * as React from 'react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import createEmotionServer from '@emotion/server/create-instance';
import theme from '../src/theme';

function getCache() {
const cache = createCache({ key: 'css', prepend: true });
cache.compat = true;
return cache;
}
import createEmotionCache from '../src/createEmotionCache';

export default class MyDocument extends Document {
render() {
Expand Down Expand Up @@ -59,21 +52,19 @@ MyDocument.getInitialProps = async (ctx) => {

const originalRenderPage = ctx.renderPage;

const cache = getCache();
// 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({
// Take precedence over the CacheProvider in our custom _app.js
enhanceComponent: (Component) => (props) =>
(
<CacheProvider value={cache}>
<Component {...props} />
</CacheProvider>
),
enhanceApp: (App) => (props) => <App emotionCache={cache} {...props} />,
});

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) => (
<style
Expand Down
5 changes: 5 additions & 0 deletions examples/nextjs/src/createEmotionCache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import createCache from '@emotion/cache';

export default function createEmotionCache() {
return createCache({ key: 'css' });
}