You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

7.4 KiB

order title
4 在 Next.js 中使用

Next.js 是目前世界上最流行的 React 服务端同构框架,本文会尝试在 Next.js 创建的工程中使用 antd 组件。

安装和初始化

在开始之前,你可能需要安装 yarn 或者 pnpm

工具会自动初始化一个脚手架并安装项目的各种必要依赖,在安装过程中,有一些配置项需要自行选择,如果在过程中出现网络问题,请尝试配置代理,或使用其他 npm registry。

初始化完成后,我们进入项目并启动。

$ cd antd-demo
$ npm run dev

此时使用浏览器访问 http://localhost:3000/ ,看到 NEXT 的 logo 就算成功了。

引入 antd

现在从 yarn 或 npm 或 pnpm 安装并引入 antd。

修改 src/app/page.tsx,引入 antd 的按钮组件。

'use client';

import React from 'react';
import { Button } from 'antd';

const Home = () => (
  <div className="App">
    <Button type="primary">Button</Button>
  </div>
);

export default Home;

好了,现在你应该能看到页面上已经有了 antd 的蓝色按钮组件,接下来就可以继续选用其他组件开发应用了。其他开发流程你可以参考 Next.js 的官方文档

我们现在已经把 antd 组件成功运行起来了,开始开发你的应用吧!

使用 Next.js 的 Pages Router

如果你在 Next.js 当中使用了 Pages Router, 并使用 antd 作为页面组件库,为了让 antd 组件库在你的 Next.js 应用中能够更好的工作,提供更好的用户体验,你可以尝试使用下面的方式将 antd 首屏样式按需抽离并植入到 HTML 中,以避免页面闪动的情况。

  1. 安装 @ant-design/cssinjs

  1. 改写 pages/_document.tsx
import { StyleProvider, createCache, extractStyle } from '@ant-design/cssinjs';
import Document, { DocumentContext, Head, Html, Main, NextScript } 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);
  // 1.1 extract style which had been used
  const style = extractStyle(cache, true);
  return {
    ...initialProps,
    styles: (
      <>
        {initialProps.styles}
        {/* 1.2 inject css */}
        <style dangerouslySetInnerHTML={{ __html: style }}></style>
      </>
    ),
  };
};

export default MyDocument;
  1. 支持自定义主题
// theme/themeConfig.ts
import type { ThemeConfig } from 'antd';

const theme: ThemeConfig = {
  token: {
    fontSize: 16,
    colorPrimary: '#52c41a',
  },
};

export default theme;
  1. 改写 pages/_app.tsx
import { ConfigProvider } from 'antd';
import type { AppProps } from 'next/app';
import theme from './themeConfig';

const App = ({ Component, pageProps }: AppProps) => (
  <ConfigProvider theme={theme}>
    <Component {...pageProps} />
  </ConfigProvider>
);

export default App;
  1. 在页面中使用 antd
import { Button } from 'antd';

const Home = () => (
  <div className="App">
    <Button type="primary">Button</Button>
  </div>
);

export default Home;

更多详细的细节可以参考 with-nextjs-inline-style

使用 Next.js 的 App Router

如果你在 Next.js 当中使用了 App Router, 并使用 antd 作为页面组件库,为了让 antd 组件库在你的 Next.js 应用中能够更好的工作,提供更好的用户体验,你可以尝试使用下面的方式将 antd 首屏样式按需抽离并植入到 HTML 中,以避免页面闪动的情况。

  1. 安装 @ant-design/cssinjs

  1. 创建 lib/AntdRegistry.tsx
import { StyleProvider, createCache, extractStyle } from '@ant-design/cssinjs';
import { useServerInsertedHTML } from 'next/navigation';
import React from 'react';

const StyledComponentsRegistry = ({ children }: { children: React.ReactNode }) => {
  const cache = createCache();
  useServerInsertedHTML(() => (
    <style id="antd" dangerouslySetInnerHTML={{ __html: extractStyle(cache, true) }} />
  ));
  return <StyleProvider cache={cache}>{children}</StyleProvider>;
};

export default StyledComponentsRegistry;
  1. app/layout.tsx 中使用
import { Inter } from 'next/font/google';
import React from 'react';
import StyledComponentsRegistry from '../lib/AntdRegistry';
import './globals.css';

const inter = Inter({ subsets: ['latin'] });

export const metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
};

const RootLayout = ({ children }: { children: React.ReactNode }) => (
  <html lang="en">
    <body className={inter.className}>
      <StyledComponentsRegistry>{children}</StyledComponentsRegistry>
    </body>
  </html>
);

export default RootLayout;
  1. theme/*.ts 中自定义主题配置
// theme/themeConfig.ts
import type { ThemeConfig } from 'antd';

const theme: ThemeConfig = {
  token: {
    fontSize: 16,
    colorPrimary: '#52c41a',
  },
};

export default theme;
  1. 在页面中使用
import { Button, ConfigProvider } from 'antd';
import React from 'react';
import theme from './themeConfig';

const HomePage: React.FC = () => (
  <ConfigProvider theme={theme}>
    <div className="App">
      <Button type="primary">Button</Button>
    </div>
  </ConfigProvider>
);

export default HomePage;

注意: 上述方式没有在页面中使用如:Select.OptionTypography.Text 等子组件,因此可以正常使用。但如果你的页面中有使用类似这样的子组件,目前在 Next.js 中会看到如下警告:Error: Cannot access .Option on the server. You cannot dot into a client module from a server component. You can only pass the imported name through.,目前需等待 Next.js 官方解决。在此之前,如果你的页面中使用了上述子组件,可在页面组件第一行加上 "use client"; 来避免警告。更多细节可以参考示例:with-sub-components

更多详细的细节可以参考 with-nextjs-app-router-inline-style