首页 博客 演讲

在 React Router v7 Framework / Remix 中避免 Ant Design 样式闪屏

2025-01-28

新版的 React Router 与 Remix 合并,变成了 React Router v7 Framework。

曾经基于 React Router 的 SPA 项目,现在也可以使用 SSR 技术来提升加载速度了。

但在使用 Ant Design 时,我们会遇到 CSS 样式懒加载导致的闪屏问题。

解决方法为修改 root.tsx 的 App 组件,使用 @ant-design/cssinjs 生成内联样式。

import {
  Outlet,
  useLocation,
} from 'react-router'
import { createCache, StyleProvider, extractStyle } from '@ant-design/cssinjs'
import { renderToString } from 'react-dom/server'
import type Entity from '@ant-design/cssinjs/lib/Cache'
import { useEffect, useInsertionEffect, useState } from 'react'

const CssCache = new Map<string, Entity>()

export default function App() {
  const location = useLocation()
  const pathname = location.pathname
  const isServer = typeof document === 'undefined'
  const cache = CssCache.get(pathname) || createCache()
  const [serverCss, setServerCss] = useState<string | null>(null)

  useInsertionEffect(() => {
    if (!CssCache.has(pathname)) {
      CssCache.set(pathname, cache)
    }
  }, [pathname, cache])

  useEffect(() => {
    if (isServer) {
      if (serverCss !== null) return

      renderToString(<StyleProvider cache={cache}>
        <Outlet />
      </StyleProvider>)

      const css = extractStyle(cache)
      setServerCss(css)
    } else {
      setServerCss('')
    }
  }, [pathname])

  if (serverCss === null) return null

  return (
    <>
      <style dangerouslySetInnerHTML={{ __html: serverCss }} />
      <Outlet />
    </>
  )
}
查看全部文章