Next.js 集成
了解如何在 Next.js 中使用 Material UI。
App Router
本节介绍 Material UI 与 Next.js App Router 的集成,它是 Pages Router 的演进,并且是目前从版本 13 开始构建新的 Next.js 应用程序的推荐方式。
安装依赖
首先确保您已经安装了 @mui/material
和 next
。然后,运行以下命令之一来安装依赖项
npm install @mui/material-nextjs @emotion/cache
配置
在 app/layout.tsx
中,导入 AppRouterCacheProvider
并将其包裹在 <body>
下的所有元素
+import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';
// or `v1X-appRouter` if you are using Next.js v1X
export default function RootLayout(props) {
return (
<html lang="en">
<body>
+ <AppRouterCacheProvider>
{props.children}
+ </AppRouterCacheProvider>
</body>
</html>
);
}
自定义缓存(可选)
使用 options
prop 覆盖默认的 缓存选项——例如,下面的代码片段展示了如何将 CSS 键更改为 css
(默认为 mui
)
<AppRouterCacheProvider
+ options={{ key: 'css' }}
>
{children}
</AppRouterCacheProvider>
字体优化
要将 Next.js 字体优化 与 Material UI 集成,请创建一个包含 'use client';
指令的新文件。然后使用 var(--font-roboto)
作为 typography.fontFamily
字段的值创建一个主题。
'use client';
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
typography: {
fontFamily: 'var(--font-roboto)',
},
});
export default theme;
最后,在 src/app/layout.tsx
中,将主题传递给 ThemeProvider
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';
+import { Roboto } from 'next/font/google';
+import { ThemeProvider } from '@mui/material/styles';
+import theme from '../theme';
+const roboto = Roboto({
+ weight: ['300', '400', '500', '700'],
+ subsets: ['latin'],
+ display: 'swap',
+ variable: '--font-roboto',
+});
export default function RootLayout(props) {
const { children } = props;
return (
+ <html lang="en" className={roboto.variable}>
<body>
<AppRouterCacheProvider>
+ <ThemeProvider theme={theme}>
{children}
+ </ThemeProvider>
</AppRouterCacheProvider>
</body>
</html>
);
}
要了解有关主题的更多信息,请查看 主题指南 页面。
CSS 主题变量
要使用 CSS 主题变量,请启用 cssVariables
标志
'use client';
const theme = createTheme({
+ cssVariables: true,
});
了解更多关于 CSS 主题变量的优势 以及如何 防止 SSR 闪烁。
使用其他样式解决方案
如果您正在使用 Emotion 以外的样式解决方案来自定义 Material UI 组件,请在 options
prop 中设置 enableCssLayer: true
<AppRouterCacheProvider options={{ enableCssLayer: true }}>
此选项确保 Material UI 生成的样式将包裹在 CSS @layer mui
规则中,当 Material UI 与 CSS Modules、Tailwind CSS 甚至不使用 @layer
的纯 CSS 一起使用时,匿名层样式会覆盖该规则。
要了解更多信息,请参阅 MDN CSS 层文档。
Pages Router
本节介绍 Material UI 与 Next.js Pages Router 的集成,适用于 服务器端渲染 (SSR) 和 静态站点生成 (SSG)。
安装依赖
首先确保您已经安装了 @mui/material
和 next
。然后,运行以下命令之一来安装依赖项
npm install @mui/material-nextjs @emotion/cache @emotion/server
配置
在 pages/_document.tsx
文件中
- 导入
documentGetInitialProps
并将其用作 Document 的getInitialProps
。 - 导入
DocumentHeadTags
并在<Head>
中渲染它。
+import {
+ DocumentHeadTags,
+ documentGetInitialProps,
+} from '@mui/material-nextjs/v15-pagesRouter';
// or `v1X-pagesRouter` if you are using Next.js v1X
export default function MyDocument(props) {
return (
<Html lang="en">
<Head>
+ <DocumentHeadTags {...props} />
...
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
+MyDocument.getInitialProps = async (ctx) => {
+ const finalProps = await documentGetInitialProps(ctx);
+ return finalProps;
+};
然后,在 pages/_app.tsx
中,导入 AppCacheProvider
组件并将其渲染为根元素
+import { AppCacheProvider } from '@mui/material-nextjs/v15-pagesRouter';
// Or `v1X-pages` if you are using Next.js v1X
export default function MyApp(props) {
return (
+ <AppCacheProvider {...props}>
<Head>
...
</Head>
...
+ </AppCacheProvider>
);
}
自定义缓存(可选)
要使用自定义的 Emotion 缓存,请将其传递给 _document.tsx
中的 emotionCache
属性
...
MyDocument.getInitialProps = async (ctx) => {
const finalProps = await documentGetInitialProps(ctx, {
+ emotionCache: createCustomCache(),
});
return finalProps;
};
App 增强功能(可选)
将数组传递给 plugins
属性以使用附加功能增强应用程序,例如,如果您正在使用 JSS 和 styled-components,则可以使用服务器端渲染的样式。
每个插件都必须具有以下属性
enhanceApp
:一个高阶组件,它接收App
组件并返回一个新的 app 组件。resolveProps
:一个函数,它接收初始 props 并返回一个新的 props 对象。
运行时,首先从上到下调用每个插件的 enhanceApp
,然后对 resolveProps
重复该过程。
import { ServerStyleSheet } from 'styled-components';
MyDocument.getInitialProps = async (ctx) => {
const jssSheets = new JSSServerStyleSheets();
const styledComponentsSheet = new ServerStyleSheet();
try {
const finalProps = await documentGetInitialProps(ctx, {
emotionCache: createEmotionCache(),
plugins: [
{
// styled-components
enhanceApp: (App) => (props) =>
styledComponentsSheet.collectStyles(<App {...props} />),
resolveProps: async (initialProps) => ({
...initialProps,
styles: [
styledComponentsSheet.getStyleElement(),
...initialProps.styles,
],
}),
},
{
// JSS
enhanceApp: (App) => (props) => jssSheets.collect(<App {...props} />),
resolveProps: async (initialProps) => {
const css = jssSheets.toString();
return {
...initialProps,
styles: [
...initialProps.styles,
<style
id="jss-server-side"
key="jss-server-side"
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: css }}
/>,
<style id="insertion-point-jss" key="insertion-point-jss" />,
],
};
},
},
],
});
return finalProps;
} finally {
styledComponentsSheet.seal();
}
};
TypeScript
如果您正在使用 TypeScript,请将 DocumentHeadTagsProps
添加到 Document 的 props 接口
+import type { DocumentHeadTagsProps } from '@mui/material-nextjs/v15-pagesRouter';
// or `v1X-pagesRouter` if you are using Next.js v1X
+export default function MyDocument(props: DocumentProps & DocumentHeadTagsProps) {
...
}
字体优化
要将 Next.js 字体优化 与 Material UI 集成,请打开 pages/_app.tsx
并使用 var(--font-roboto)
作为 typography.fontFamily
字段的值创建一个主题。
import * as React from 'react';
import Head from 'next/head';
import { AppProps } from 'next/app';
import { AppCacheProvider } from '@mui/material-nextjs/v15-pagesRouter';
+import { ThemeProvider, createTheme } from '@mui/material/styles';
+import { Roboto } from 'next/font/google';
+const roboto = Roboto({
+ weight: ['300', '400', '500', '700'],
+ subsets: ['latin'],
+ display: 'swap',
+ variable: '--font-roboto',
+});
+const theme = createTheme({
+ typography: {
+ fontFamily: 'var(--font-roboto)',
+ },
+});
export default function MyApp(props: AppProps) {
const { Component, pageProps } = props;
return (
<AppCacheProvider {...props}>
<Head>...</Head>
+ <ThemeProvider theme={theme}>
+ <main className={roboto.variable}>
<Component {...pageProps} />
+ </main>
+ </ThemeProvider>
</AppCacheProvider>
);
}
要了解有关主题的更多信息,请查看 主题指南。
CSS 主题变量
要使用 CSS 主题变量,请启用 cssVariables
标志
'use client';
const theme = createTheme({
+ cssVariables: true,
});
了解更多关于 CSS 主题变量的优势 以及如何 防止 SSR 闪烁。