问题1:CSS和JS在网页中的放置顺序是怎样的
CSS应该放在页面顶部的
head
标签中
由于Render Tree是由DOM树和CSSOM树组合成的,html页面需要等到CSS解析完后才能完成渲染,所以CSS应放在head
标签内,优先下载解析,以避免页面元素由于样式缺失造成瞬间的白屏和闪烁。JS应该放在
body
的底部
- 因为浏览器需要一个稳定的dom树结构,而且js中很有可能有代码直接改变了dom树结构,浏览器为了防止出现js修改dom树,需要重新构建dom树的情况,所以就会阻塞其他的下载和呈现。
- 将JavaScript放在head内和body底部的区别也在于此,放在head里面,由于浏览器发现head里面有JavaScript标签就会暂时停止其他渲染行为,等待JavaScript下载并执行完成才能接着往下渲染,而这个时候由于在head里面这个时候页面是白的;如果JavaScript放在页面底部,render Tree已经完成大部分,所以此时页面有内容呈现,即使遇到JavaScript阻塞渲染,也不会有白屏出现。
- 如果CSS和JS都在
head
标签内,则应将JS放在所有CSS的前面
head里的内联js只要在所有外联css前面,css文件就可以和body里的请求并行。因为JS 的执行有可能依赖最新样式。比如,可能会有 var width = $('#id').width(). 这意味着,JS 代码在执行前,浏览器必须保证在此 JS 之前的所有 css(无论外链还是内嵌)都已下载和解析完成。这是 CSS 阻塞后续 JS 执行的根本原因。
问题2:解释白屏和FOUC
- 白屏和fouc并不是bug,而是不同浏览器加载和显示机制不同造成的。解决方法就是使用
link
标签将样式表放置在head
标签中 - 白屏
1.当把css样式放在底部或者使用@import
方式引入样式时一些浏览器例如chrome和IE,他的加载和渲染机制是等css全部加载解析完后再渲染展示页面,而这个等待的时间就为白屏。
2.如果把js文件放在头部,脚本会阻塞后面内容的呈现,脚本会阻塞其后组件的下载,出现白屏问题。 - FOUC
逐步加载无样式的内容,等CSS加载后页面突然展现样式
1.如果把CSS样式放在底部,对于IE浏览器,在某些场景下(点击链接,输入URL,使用书签进入等),会出现 FOUC .
2.另一些浏览器例如Firefox,他会在css未加载前先展现页面,等css加载后再重新对样式进行修改,这就造成了FOUC 。
问题3:async和defer的作用是什么?有什么区别?
如果既不使用 async 也不使用 defer:在浏览器继续解析页面之前,立即读取并执行脚本。
默认引用 script:<script type="text/javascript" src="script.js"></script>
当浏览器遇到 script 标签时,文档的解析将停止,并立即下载并执行脚本,脚本执行完毕后将继续解析文档。async模式 <script type="text/javascript" src="script.js" async="async"></script>
当浏览器遇到 script 标签时,文档的解析不会停止,其他线程将下载脚本,脚本下载完成后开始执行脚本,脚本执行的过程中文档将停止解析,直到脚本执行完毕。defer模式 <script type="text/javascript" src="script.js" defer="defer"></script>
当浏览器遇到 script 标签时,文档的解析不会停止,其他线程将下载脚本,待到文档解析完成,脚本才会执行。区别
最主要的区别就是async是异步下载并立即执行,然后文档继续解析,defer是异步加载后解析文档,然后再执行脚本。
问题3:简述网页的渲染机制
-
浏览器解析(包括HTML,SVG,XHTML,CSS,JavaScript等等)
解析HTML代码,构建Document Object Model (DOM)
解析CSS代码,构建CSS Object Model (CSSOM)
JavaSript通过API操作DOM和CSSOM,
渲染树构建过程如下:
布局阶段
在屏幕上绘制渲染树中的所有节点的几何属性,比如: 位置,宽高,大小等等绘制元素
绘制所有节点的可视属性,比如:颜色,背景,边框,背景图等,这期间可能会产生多个图层(堆叠上下文)。合并渲染层
把以上绘制的所有图层(类似于PhotoShop中的“图层”)合并,最终输出一张图片。
文/饥人谷小霾(简书作者)著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。