Next.js 是目前世界上最受欢迎的 React 服务端同构框架。本文将介绍如何在 Next.js 创建的项目中使用 Ant Design 组件。
安装与初始化
在开始之前,你需要安装 yarn、pnpm 或 bun。
# 使用 pnpm 创建 Next.js 项目
$ pnpm create next-app antd-demo
该工具会自动创建并初始化环境和依赖。如果在过程中遇到网络问题,请尝试配置代理设置或使用其他 npm registry。
初始化完成后,进入项目并启动开发服务器。
$ cd antd-demo $ npm run dev
在浏览器中打开 http://localhost:3000/,如果看到 NEXT 的 logo,表示成功。
引入 Ant Design
现在,我们使用 yarn 或 npm 或 pnpm 或 bun 安装 antd。
# 安装 antd
$ npm install antd --save
修改 src/app/page.tsx
,引入 antd 的 Button 组件。
import React from 'react'; import { Button } from 'antd'; const Home = () => ( <div className="App"> <Button type="primary">Button</Button> </div> ); export default Home;
此时,你应该可以在页面上看到一个蓝色的 primary 按钮。接下来,你可以选择 antd 的任何组件来开发你的应用。
使用 App Router 模式
如果你在 Next.js 中使用 App Router 并且使用 antd 作为你的组件库,为了更好地在 Next.js 应用中使用 antd 组件库,并提供更好的用户体验,可以尝试使用以下方法将 antd 的首屏样式提取并注入 HTML,以避免页面闪烁。
安装 @ant-design/nextjs-registry
# 安装 @ant-design/nextjs-registry
$ npm install @ant-design/nextjs-registry --save
在 app/layout.tsx
中使用它
import React from 'react'; import { AntdRegistry } from '@ant-design/nextjs-registry'; const RootLayout = ({ children }: React.PropsWithChildren) => ( <html lang="en"> <body> <AntdRegistry>{children}</AntdRegistry> </body> </html> ); export default RootLayout;
注意:Next.js App Router 目前不支持通过 . 方式使用子组件,比如 <Select.Option />
和 <Typography.Text />
。可以通过路径导入解决此问题。
使用 Pages Router 模式
如果你在 Next.js 中使用 Pages Router 并且使用 antd 作为你的组件库,为了更好地在 Next.js 应用中使用 antd 组件库,并提供更好的用户体验,可以尝试使用以下方法将 antd 的首屏样式提取并注入 HTML,以避免页面闪烁。
安装 @ant-design/cssinjs
请注意,安装 @ant-design/cssinjs
时,必须确保其版本与 antd 本地 node_modules 中的 @ant-design/cssinjs
版本一致,否则会出现多个 React 实例,导致 ctx 无法正确读取的问题。
# 安装 @ant-design/cssinjs
$ npm install @ant-design/cssinjs --save
重写 pages/_document.tsx
import React from 'react'; import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs'; import Document, { Head, Html, Main, NextScript } from 'next/document'; import type { DocumentContext } from 'next/document'; const MyDocument = () => ( <Html lang="en"> <Head /> <body> <Main /> <NextScript /> </body> </Html> ); MyDocument.getInitialProps = async (ctx: DocumentContext) => { const cache = createCache(); const originalRenderPage = ctx.renderPage; ctx.renderPage = () => originalRenderPage({ enhanceApp: (App) => (props) => ( <StyleProvider cache={cache}> <App {...props} /> </StyleProvider> ), }); const initialProps = await Document.getInitialProps(ctx); const style = extractStyle(cache, true); return { ...initialProps, styles: ( <> {initialProps.styles} <style dangerouslySetInnerHTML={{ __html: style }} /> </> ), }; }; export default MyDocument;
支持自定义主题
theme/themeConfig.ts
import type { ThemeConfig } from 'antd'; const theme: ThemeConfig = { token: { fontSize: 16, colorPrimary: '#52c41a', }, }; export default theme;
重写 pages/_app.tsx
import React from 'react'; import { ConfigProvider } from 'antd'; import type { AppProps } from 'next/app'; import theme from './theme/themeConfig'; const App = ({ Component, pageProps }: AppProps) => ( <ConfigProvider theme={theme}> <Component {...pageProps} /> </ConfigProvider> ); export default App;
在页面组件中使用 antd
import React from 'react'; import { Button } from 'antd'; const Home = () => ( <div className="App"> <Button type="primary">Button</Button> </div> ); export default Home;
更多详细信息,请参考 with-nextjs-inline-style.