这是个在做《阅读海洋》移动端遇到的问题…

FOUC (Flash of Unstyled Content) 无样式内容闪烁

产生原因

关于产生原因,这涉及到了浏览器的渲染机制,关于浏览器的渲染机制我以后会单独写一篇文章进行分析。

总结出一个(不太准确的)原因:在用户自定的 CSS 样式表加载之前,部分元素会以浏览器内置样式(User Agent Stylesheet)去渲染,等到用户自定的 CSS 样式表加载完成后,浏览器刷新了 CSSOM Tree 导致 Render Tree 也被刷新,网页发生重绘(repaint)及回流(reflow),导致页面闪烁。

这里先引入两个概念:

  • Block Parsing: 阻塞 HTML 页面解析,HTML 页面会被继续下载,但阻塞点后面的标签不会被解析,<img> , <link> 等标签不会发请求获取外部资源。
  • Block Rendering:阻塞 HTML 页面渲染,HTML 页面会被继续下载,阻塞点后面的标签会继续被解析,<img> , <link> 等标签会继续发送请求获取外部资源,但不会合成 Render Tree 或不会触发页面渲染,也不会执行 JavaScript 代码。

但因为各浏览器处理机制不同,所表现的现象也不同。

(据我了解,Chrome 一般是白屏,等到 CSS 完全加载后再渲染出页面,而 FireFox 则是出现 FOUC 情况。)

以下总结出几个可能导致 FOUC 的原因:

  • 使用 @import 导入样式表 (老 IE) (还会导致在关键渲染路径中增加往返次数)

  • 将样式表放在了页面的底部

  • 有几个样式表,分别放在页面不同的位置 (《阅读海洋》项目出现 FOUC 就是这个原因导致)

解决方案

  • 使用 <link> 标签将样式表放在文档的 <head> 中,这样就可以在 <body> 渲染前把 CSSOM Tree 构建好。

关键渲染路径(Critical Rendering Path)

这是我大学刚入学接触到的一个关键词,但当时没有深究其含义,想着以后遇到再说。

终于,现在有机会遇到了,是时候分析一下以便更好的理解。

关键渲染路径:指浏览器从收到 HTML、CSS 和 JavaScript 字节开始,到绘制页面时需要做的一系列行为。

而现在讲的前端优化,有很大一部分就是指 CRP 的优化。

关于 CRP 的优化,一般有以下三个指标:

  • 关键资源: 可能阻止网页首次渲染的资源。
  • 关键路径长度: 获取所有关键资源所需的往返次数或总时间。
  • 关键字节: 实现网页首次渲染所需的总字节数,它是所有关键资源传送文件大小的总和。我们包含单个 HTML 页面的第一个示例包含一项关键资源(HTML 文档);关键路径长度也与 1 次网络往返相等(假设文件较小),而总关键字节数正好是 HTML 文档本身的传送大小。

而现在讲的前端优化,有很大一部分就是指 CRP 的优化。

为了让自己更好的理解,我觉得还是有必要另外写一篇文章说说 CRP 的定义,以及如何优化 CRP 啦!

参考链接:腾讯云社区:Web 性能优化 - 关键渲染路径以及优化策略