如何解决 SSR 中的样式闪烁问题?
服务端渲染中,样式闪烁是常见的一个问题。本文详细分析了其原因,并给出了多种解决方案,如将 CSS 置于头部、避免使用 @import、嵌入关键 CSS 以及利用框架工具处理异步样式管理。
FOUC (文档样式短暂失效) 是指在服务端渲染 (SSR) 中,由于样式加载延迟或渲染顺序不当,导致用户短暂看到未应用样式的 HTML 内容,随后样式加载完成后重新渲染引起的页面闪烁现象。在 SSR 中,HTML 由服务器生成后发送至客户端,但若 CSS 引用不当或在客户端渲染过程中加载滞后,会造成此问题。
以下针对 FOUC 的原因及解决方法进行详细阐述:
SSR 中出现 FOUC 的常见原因
- 样式加载延迟:CSS 文件放置于页面底部或经动态 JavaScript 导入(如 @import 指令),在 DOM 加载后被逐步加载。
- 异步样式管理:在使用 SSR 框架(如 React)时,组件级样式需在客户端渲染后通过脚本注入,导致页面初次渲染无样式。
- 网络依赖:外部 CSS 文件的加载依赖于低速网络或大文件尺寸,延长“文档解析完成—样式应用”的时间差。
解决方法 (重点针对 SSR 优化优化优化)
- 样式文件置于头部
- 将所有 CSS 用 标签在 HTML head 引入
<head> <link rel="stylesheet" type="text/css" href="styles.css"> </head>
- 好处: 浏览器优先加载并解析 CSS,减少加载空窗。
- 避免使用 @import 导入样式
- 不使用如“CSS Modules 外链方式”,改用“链接式加载:
// 避免:在 CSS 文件中用 @import @import url('external.css');
- 替代: 在 HTML 直接多文件或集成合并 CSS。
- 嵌入关键 CSS(针对 SSR)
- 通过工具提取“第一屏关键样式”内联进 HTML(提升首屏加载体验不依赖外网响应。
- Next.js 示例如利用 CSS-in-JS 动态收集样式并嵌入:
import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs'; function RootStyleRegistry({ children }) { const cache = createCache(); useServerInsertedHTML(() => ( <style dangerouslySetInnerHTML={{ __html: extractStyle(cache)}} /> )); return <StyleProvider cache={cache}>{children}</StyleProvider>; } // 然后作为提供者在根布局中包裹应用 export default function RootLayout({ children }) { return <RootStyleRegistry>{children}</RootStyleRegistry>; }
- 利用框架 SSR/工具处理异步样式管理(如 Next.js)
- 如果使用的是 React(Next.js框架),则安装 @ant-design/cssinjs:
npm i @ant-design/cssinjs
将整个页面的初始 CSS 收集并在首屏刷新前注入。
- 如果使用的是 React(Next.js框架),则安装 @ant-design/cssinjs:
- 优化加载顺序避免干扰渲染
- JS运行推迟与同步资源等待保证“CSS前置渲染完成”.
通过如上策略可消除首次加载的样式闪烁影响用户视觉体验;当采取这些方法后 SSR渲染首屏加载更为连续高效。