- Ant Design of React
- v5.21.0Changelog
- Basic Usage
- Advanced
- Migration
- Other
Server Side Rendering
There are two options for server-side rendering styles, each with advantages and disadvantages:
Use @ant-design/cssinjs
to extract style:
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 Renderconst cache = React.useMemo<Entity>(() => createCache(), []);const html = renderToString(<StyleProvider cache={cache}><MyApp /></StyleProvider>,);// Grab style from cacheconst styleText = extractStyle(cache);// Mix with stylereturn `<!DOCTYPE html><html><head>${styleText}</head><body><div id="root">${html}</div></body></html>`;};export default App;
If you want to detach a style file into a css file, try the following schemes:
npm install ts-node tslib cross-env --save-dev
tsconfig.node.json
{"compilerOptions": {"strictNullChecks": true,"module": "NodeNext","jsx": "react","esModuleInterop": true},"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]}
scripts/genAntdCss.tsx
// scripts/genAntdCss.tsximport fs from 'fs';import { extractStyle } from '@ant-design/static-style-extract';const outputPath = './public/antd.min.css';const css = extractStyle();fs.writeFileSync(outputPath, css);
If you want to use mixed themes or custom themes, you can use the following script:
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) => (<><ConfigProvidertheme={{token: {colorBgBase: testGreenColor,},}}>{node}</ConfigProvider><ConfigProvidertheme={{token: {colorPrimary: testGreenColor,},}}><ConfigProvidertheme={{token: {colorBgBase: testRedColor,},}}>{node}</ConfigProvider></ConfigProvider></>));fs.writeFileSync(outputPath, css);
You can choose to execute this script before starting the development command or before compiling. Running this script will generate a full antd.min.css file directly in the specified directory of the current project (e.g. public).
Take Next.js for example(example):
// 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"}}
Then, you just need to import this file into the pages/_app.tsx
file:
import { StyleProvider } from '@ant-design/cssinjs';import type { AppProps } from 'next/app';import '../public/antd.min.css'; // add this lineimport '../styles/globals.css';export default function App({ Component, pageProps }: AppProps) {return (<StyleProvider hashPriority="high"><Component {...pageProps} /></StyleProvider>);}
If you're using a custom theme for your project, try baking in the following ways:
import { extractStyle } from '@ant-design/static-style-extract';import { ConfigProvider } from 'antd';const cssText = extractStyle((node) => (<ConfigProvidertheme={{token: {colorPrimary: 'red',},}}>{node}</ConfigProvider>));
If you're using a mixed theme for your project, try baking in the following ways:
import { extractStyle } from '@ant-design/static-style-extract';import { ConfigProvider } from 'antd';const cssText = extractStyle((node) => (<><ConfigProvidertheme={{token: {colorBgBase: 'green ',},}}>{node}</ConfigProvider><ConfigProvidertheme={{token: {colorPrimary: 'blue',},}}><ConfigProvidertheme={{token: {colorBgBase: 'red ',},}}>{node}</ConfigProvider></ConfigProvider></>));
More about static-style-extract, see static-style-extract.
// scripts/genAntdCss.tsximport { 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 type DoExtraStyleOptions = {cache: Entity;dir?: string;baseFileName?: string;};export function doExtraStyle({cache,dir = 'antd-output',baseFileName = 'antd.min',}: DoExtraStyleOptions) {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;}
Export on demand using the above tools in _document.tsx
// _document.tsximport { 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 usedfileName = 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>);}}
See the demo:Export the css files on demand demo