博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前端魔法堂:解秘FOUC
阅读量:6702 次
发布时间:2019-06-25

本文共 2585 字,大约阅读时间需要 8 分钟。

 对于问题多多的IE678,FOUC(flash of unstyled content)——浏览器样式闪烁是一个不可忽视的话题,但对于ever green的浏览器就不用理会了吗?下面尝试较全面地解密FOUC。

到底什么是FOUC?

 页面加载解析时,页面以样式A渲染;当页面加载解析完成后,页面突然以样式B渲染,导致出现页面样式闪烁。

样式A,浏览器默认样式 或 浏览器默认样式 层叠 部分已加载的页面样式;
样式B,浏览器默认样式 叠加 全部页面样式。

为什么会出现FOUC

 我们了解当输入网址按回车后浏览器会向服务器发送请求,然后服务器返回页面给浏览器,浏览器边下载页面边解析边渲染。

下面我们解剖一下边下载页面边解析边渲染的过程:

  1. 边下载边解析就是边下载html边构建DOM Tree;
  2. 浏览器以user agent stylesheet(浏览器内置样式)为原料构建CSSOM Tree;
  3. DOM Tree+CSSOM Tree构建出Render Tree,然后页面内容渲染出来;
  4. 当解析到inline stylesheet 或 internal stylesheet时,马上刷新CSSOM Tree,CSSOM Tree或DOM Tree发生变化时会引起Render Tree变化;
  5. 当解析到external stylesheet时就先加载,然后如internal stylesheet那样解析和刷新CSSOM Tree和Render Tree了。
    上述步骤5中由于样式文件存在下载这个延时不确定的阶段,因此网络环境不好或样式资源体积大的情况下我们可以看到样式闪烁明显。
    这就是为什么我们将external stylesheet的引入放在head标签中的原因,在body渲染前先把相对完整的CSSOM Tree构建好。但大家都听说过script会阻塞html页面解析(block parsing),而link不会,那假如网络环境不好或样式资源体积大时,body已经解析并加入到DOM Tree后,external stylesheet才加载完成,不是也会造成FOUC吗?
    style,link等样式资源的下载、解析确实不会阻塞页面的解析,但它们会阻塞页面的渲染(block rendering)。

Block Parsing 和 Block Rendering的区别

Block Parsing: 阻塞HTML页面解析,HTML页面会被继续下载,但阻塞点后面的标签不会被解析,img,link等不会发请求获取外部资源。

Block Rendering:阻塞HTML页面渲染,HTML页面会被继续下载,阻塞点后面的标签会继续被解析,img,link等会继续发送请求获取外部资源,但不会合成Rendering Tree或不会触发页面渲染,也不会执行JavaScript代码。
各浏览器这方面还有一点差异:

对于Chrome

<link rel="stylesheet">,<link rel="import"> and @import url("<url>")会阻塞渲染。

示例1:阻塞解析

              
Hi

示例2:阻塞渲染

          
Hi

示例3:阻塞渲染

          
Hi

示例4:阻塞渲染

          
Hi

示例2说明,如果阻塞渲染发生在body标签内,那么body及其子元素会继续解析并追加到DOM Tree中;

示例3说明,如果阻塞渲染发生在head标签内,那么body及其子元素不会被追加到DOM Tree中。
示例4说明,不管external stylesheet在哪里引入,在页面的所有external stylesheets下载完成前(DOMContentLoaded后才渲染),整个页面将不会被渲染。(估计Chrome会预先统计external stylesheet的数量)

对于FireFox

示例1:阻塞渲染

          
Hi

示例2:阻塞渲染

          
Hi

对于IE9

示例1:

          
Hi

示例2:

          
Hi

上面的示例表明,IE下block rendering等价于block parsing,因为连img,script,link,@import url()资源请求都会被阻塞。

解决方法

 现在我们知道FOUC时由于页面采用临时样式来渲染页面而导致的,其中仅有chrome能好的屏蔽了这一点,而其他浏览器就呵呵了。那有什么方案可以解决呢?其实我们的目的就是不要让用户看到临时样式,那么我们可以隐藏body,当样式资源加载完成后再显示body

                    

(编译modernizr时记得勾setClasses哦,否则不会替换no-js的!)

总结

 上述方案虽然解决了FOUC的问题,但很明显地延长了首屏白屏时间,当前较流行的App Shell(可以理解为先显示页面布局的骨架或一幅图片)也会失效,所以对于2C的应用仅仅采用上述的方案效果并不理想。后续待我研究好后再追加一篇吧^^

尊重原创,转载请注明来自: ^^肥仔John

感谢

如果您觉得本文的内容有趣就扫一下吧!捐赠互勉!

分类: ,
+加关注
0
0
上一篇:
下一篇:
posted @ 2017-04-20 15:37 阅读( 322) 评论( 0)
 
最新IT新闻:
·
·
·
·
·
»
最新知识库文章:
·
·
·
·
·
»

公告

本文转自博客园博客,原文链接:,如需转载请自行联系原作者

 

 

你可能感兴趣的文章
开源欣赏wordpress之post.php
查看>>
Fabio 安装和简单使用
查看>>
tp5中的配置机制
查看>>
OpenGL入门笔记(九)
查看>>
phpcms使用session的方法
查看>>
对PostgreSQL数据库的hstore类型建立GisT索引的实验
查看>>
隐马尔可夫模型(七)——隐马尔可夫模型的学习问题(前向后向算法)
查看>>
Docker 部署 SpringBoot 项目整合 Redis 镜像做访问计数Demo
查看>>
常用Maven插件介绍
查看>>
Flex和Fms3打造在线聊天室(利用NetConnection对象和SharedObject对象)
查看>>
Kotlin Android学习入门
查看>>
[Oracle]跨越 DBLINK 访问表时,数据缓存在何处的Data Buffer 中?
查看>>
订单数字提醒的实现
查看>>
Cassandra概念学习系列之Cassandra是什么?
查看>>
C#模拟网站页面POST数据提交表单(二)--HttpWebRequest以及HttpWebResponse (转)
查看>>
open-falcon ---安装Dashboard时候报错"SSLError: The read operation timed out"
查看>>
FLEX程序设计--事件和事件机制--键盘事件
查看>>
【重构笔记04】重新组织数据(2)
查看>>
在VC中如何才能得到当前屏幕的分辨率
查看>>
一个Linux脚本搞定常用软件的安装
查看>>