logoAnt Design

⌘ K
  • 设计
  • 研发
  • 组件
  • 博客
  • 资源
  • 国内镜像
5.25.4
  • Ant Design of React
  • 更新日志
    v5.25.4
  • 如何使用
    • 快速上手
    • 在 Vite 中使用
    • 在 Next.js 中使用
      Updated
    • 在 Umi 中使用
    • 在 Rsbuild 中使用
    • 在 Farm 中使用
    • 使用 Refine
  • 进阶使用
    • 定制主题
    • 样式兼容
    • 服务端渲染
    • 使用 CSS 变量
      New
    • 使用自定义日期库
    • 国际化
    • 通用属性
    • React 19 兼容
      New
  • 迁移
    • 从 v4 到 v5
    • 从 Less 变量到 Design Token
  • 其他
    • 社区精选组件
    • 贡献指南
    • FAQ
内联样式
整体导出
自定义主题
混合主题
按需抽取

服务端渲染

文档贡献者
  • 样式兼容使用 CSS 变量

    相关资源

    Ant Design X
    Ant Design Charts
    Ant Design Pro
    Pro Components
    Ant Design Mobile
    Ant Design Mini
    Ant Design Web3
    Ant Design Landing-首页模板集
    Scaffolds-脚手架市场
    Umi-React 应用开发框架
    dumi-组件/文档研发工具
    qiankun-微前端框架
    Ant Motion-设计动效
    国内镜像站点 🇨🇳

    社区

    Awesome Ant Design
    Medium
    Twitter
    yuque logoAnt Design 语雀专栏
    Ant Design 知乎专栏
    体验科技专栏
    seeconf logoSEE Conf-蚂蚁体验科技大会
    加入我们

    帮助

    GitHub
    更新日志
    常见问题
    报告 Bug
    议题
    讨论区
    StackOverflow
    SegmentFault

    Ant XTech logo更多产品

    yuque logo语雀-构建你的数字花园
    AntV logoAntV-数据可视化解决方案
    Egg logoEgg-企业级 Node.js 框架
    Kitchen logoKitchen-Sketch 工具集
    Galacean logoGalacean-互动图形解决方案
    xtech logo蚂蚁体验科技
    主题编辑器
    Made with ❤ by
    蚂蚁集团和 Ant Design 开源社区

    服务端渲染样式有两种方案,它们各有优缺点:

    • 内联样式:在渲染时无需额外请求样式文件,好处是减少额外的网络请求,缺点则是会使得 HTML 体积增大,影响首屏渲染速度,相关讨论参考:#39891
    • 整体导出:提前烘焙 antd 组件样式为 css 文件,在页面中时引入。好处是打开任意页面时如传统 css 方案一样都会复用同一套 css 文件以命中缓存,缺点是如果页面中存在多主题,则需要额外进行烘焙

    内联样式

    使用 @ant-design/cssinjs 将所需样式抽离:

    tsx
    import React from 'react';
    import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs';
    import type Entity from '@ant-design/cssinjs/es/Cache';
    import { renderToString } from 'react-dom/server';
    const App = () => {
    // SSR Render
    const cache = React.useMemo<Entity>(() => createCache(), []);
    const html = renderToString(
    <StyleProvider cache={cache}>
    <MyApp />
    </StyleProvider>,
    );
    // Grab style from cache
    const styleText = extractStyle(cache);
    // Mix with style
    return `
    <!DOCTYPE html>
    <html>
    <head>
    ${styleText}
    </head>
    <body>
    <div id="root">${html}</div>
    </body>
    </html>
    `;
    };
    export default App;

    整体导出

    如果你想要将样式文件抽离到 css 文件中,可以尝试使用以下方案:

    1. 安装依赖
    bash
    npm install ts-node tslib cross-env --save-dev
    1. 新增 tsconfig.node.json 文件
    json
    {
    "compilerOptions": {
    "strictNullChecks": true,
    "module": "NodeNext",
    "jsx": "react",
    "esModuleInterop": true
    },
    "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
    }
    1. 新增 scripts/genAntdCss.tsx 文件
    tsx
    // scripts/genAntdCss.tsx
    import fs from 'fs';
    import { extractStyle } from '@ant-design/static-style-extract';
    const outputPath = './public/antd.min.css';
    const css = extractStyle();
    fs.writeFileSync(outputPath, css);

    若你想使用混合主题或自定义主题,可采用以下脚本:

    tsx
    import fs from 'fs';
    import React from 'react';
    import { extractStyle } from '@ant-design/static-style-extract';
    import { ConfigProvider } from 'antd';
    const outputPath = './public/antd.min.css';
    const testGreenColor = '#008000';
    const testRedColor = '#ff0000';
    const css = extractStyle((node) => (
    <>
    <ConfigProvider
    theme={{
    token: {
    colorBgBase: testGreenColor,
    },
    }}
    >
    {node}
    </ConfigProvider>
    <ConfigProvider
    theme={{
    token: {
    colorPrimary: testGreenColor,
    },
    }}
    >
    <ConfigProvider
    theme={{
    token: {
    colorBgBase: testRedColor,
    },
    }}
    >
    {node}
    </ConfigProvider>
    </ConfigProvider>
    </>
    ));
    fs.writeFileSync(outputPath, css);

    你可以选择在启动开发命令或编译前执行这个脚本,运行上述脚本将会在当前项目的指定(如: public 目录)目录下直接生成一个全量的 antd.min.css 文件。

    以 Next.js 为例(参考示例):

    json
    // package.json
    {
    "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "predev": "ts-node --project ./tsconfig.node.json ./scripts/genAntdCss.tsx",
    "prebuild": "cross-env NODE_ENV=production ts-node --project ./tsconfig.node.json ./scripts/genAntdCss.tsx"
    }
    }

    然后,你只需要在pages/_app.tsx文件中引入这个文件即可:

    tsx
    import { StyleProvider } from '@ant-design/cssinjs';
    import type { AppProps } from 'next/app';
    import '../public/antd.min.css'; // 添加这行
    import '../styles/globals.css';
    export default function App({ Component, pageProps }: AppProps) {
    return (
    <StyleProvider hashPriority="high">
    <Component {...pageProps} />
    </StyleProvider>
    );
    }

    自定义主题

    如果你的项目中使用了自定义主题,可以尝试通过以下方式进行烘焙:

    tsx
    import { extractStyle } from '@ant-design/static-style-extract';
    import { ConfigProvider } from 'antd';
    const cssText = extractStyle((node) => (
    <ConfigProvider
    theme={{
    token: {
    colorPrimary: 'red',
    },
    }}
    >
    {node}
    </ConfigProvider>
    ));

    混合主题

    如果你的项目中使用了混合主题,可以尝试通过以下方式进行烘焙:

    tsx
    import { extractStyle } from '@ant-design/static-style-extract';
    import { ConfigProvider } from 'antd';
    const cssText = extractStyle((node) => (
    <>
    <ConfigProvider
    theme={{
    token: {
    colorBgBase: 'green ',
    },
    }}
    >
    {node}
    </ConfigProvider>
    <ConfigProvider
    theme={{
    token: {
    colorPrimary: 'blue',
    },
    }}
    >
    <ConfigProvider
    theme={{
    token: {
    colorBgBase: 'red ',
    },
    }}
    >
    {node}
    </ConfigProvider>
    </ConfigProvider>
    </>
    ));

    更多static-style-extract的实现细节请看:static-style-extract。

    按需抽取

    tsx
    // scripts/genAntdCss.tsx
    import { createHash } from 'crypto';
    import fs from 'fs';
    import path from 'path';
    import { extractStyle } from '@ant-design/cssinjs';
    import type Entity from '@ant-design/cssinjs/lib/Cache';
    export interface DoExtraStyleOptions {
    cache: Entity;
    dir?: string;
    baseFileName?: string;
    }
    export const doExtraStyle = (opts: DoExtraStyleOptions) => {
    const { cache, dir = 'antd-output', baseFileName = 'antd.min' } = opts;
    const baseDir = path.resolve(__dirname, '../../static/css');
    const outputCssPath = path.join(baseDir, dir);
    if (!fs.existsSync(outputCssPath)) {
    fs.mkdirSync(outputCssPath, { recursive: true });
    }
    const css = extractStyle(cache, true);
    if (!css) {
    return '';
    }
    const md5 = createHash('md5');
    const hash = md5.update(css).digest('hex');
    const fileName = `${baseFileName}.${hash.substring(0, 8)}.css`;
    const fullpath = path.join(outputCssPath, fileName);
    const res = `_next/static/css/${dir}/${fileName}`;
    if (fs.existsSync(fullpath)) {
    return res;
    }
    fs.writeFileSync(fullpath, css);
    return res;
    };

    在 _document.tsx 中使用上述工具进行按需导出:

    tsx
    // _document.tsx
    import { createCache, StyleProvider } from '@ant-design/cssinjs';
    import type { DocumentContext } from 'next/document';
    import Document, { Head, Html, Main, NextScript } from 'next/document';
    import { doExtraStyle } from '../scripts/genAntdCss';
    export default class MyDocument extends Document {
    static async getInitialProps(ctx: DocumentContext) {
    const cache = createCache();
    let fileName = '';
    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
    fileName = doExtraStyle({
    cache,
    });
    return {
    ...initialProps,
    styles: (
    <>
    {initialProps.styles}
    {/* 1.2 inject css */}
    {fileName && <link rel="stylesheet" href={`/${fileName}`} />}
    </>
    ),
    };
    }
    render() {
    return (
    <Html lang="en">
    <Head />
    <body>
    <Main />
    <NextScript />
    </body>
    </Html>
    );
    }
    }

    演示示例请看:按需抽取样式示例