问题
因为之前 Next 和 React 接连出现安全问题,于是把博客的依赖升级了一下,没想到就搞出问题了,如下图所示:
初次渲染时样式丢失,在客户端上会短暂展示 Antd 组件无样式界面,出现样式闪烁的情况。项目是 Next 14,React 18 的 App Router 项目,依赖版本:"@ant-design/nextjs-registry": "^1.3.0","antd": "^5.14.2"。
解决思路
因为 Antd 是 CSS-in-js 的 UI 库,按照官方文档呢,我们需要一个 @ant-design/nextjs-registry 包裹整个页面,在 SSR 时收集所有组件的样式,并且通过 <script> 标签在客户端首次渲染时带上。- // src/app/layout.tsx
- import { AntdRegistry } from '@ant-design/nextjs-registry'
- export default async function RootLayout({
- children
- }: Readonly<{
- children: React.ReactNode
- }>) {
- return (
- <html lang="en">
- <head>
- {/* ... */}
- </head>
- <body>
-
- {/* ... 假装这是页面代码 */}
- </AntdRegistry>
- </body>
- </html>
- )
- }
复制代码 对照了一下官方文档也问了下 AI,没发现我的写法有什么问题。就在这个时候,我猛然间看见了 Antd 的 Pages Router 使用的注意事项:
我寻思,可能我遇到的情况和这里一样,是内部依赖版本 @ant-design/cssinj 不对引起的。
输入 npm ls @ant-design/cssinjs 看了一下,- ├─┬ @ant-design/nextjs-registry@1.3.0
- │ └── @ant-design/cssinjs@2.0.1
- └─┬ antd@5.14.2
- └── @ant-design/cssinjs@1.24.0 deduped
复制代码 @ant-design/nextjs-registry 内部也使用了 @ant-design/cssinjs,而且它的版本和 antd 内置版本还不一样,这就是问题的所在了。
接下来把 @ant-design/nextjs-registry 的版本降到了 1.2.0,这时候版本对上了,bug 也就修复了。- ├─┬ @ant-design/nextjs-registry@1.2.0
- │ └── @ant-design/cssinjs@1.24.0
- └─┬ antd@5.14.2
- └── @ant-design/cssinjs@1.24.0 deduped
复制代码 @ant-design/nextjs-registry 的内部发生了什么
AntdRegistry
这勾起了我的好奇心,就让我们来看看 @ant-design/nextjs-registry 干了些什么:
https://github.com/ant-design/nextjs-registry
[code]// /src/AntdRegistry.tsx'use client';import type { StyleProviderProps } from '@ant-design/cssinjs';import type { FC } from 'react';import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs';import { useServerInsertedHTML } from 'next/navigation';import React, { useState } from 'react';type AntdRegistryProps = Omit;const AntdRegistry: FC = (props) => { const [cache] = useState(() => createCache()); useServerInsertedHTML(() => { const styleText = extractStyle(cache, { plain: true, once: true }); if (styleText.includes('.data-ant-cssinjs-cache-path{content:"";}')) { return null; } return ( |