CSS和JS在网页中的放置顺序是怎样的?
- CSS应该放在页面顶部的head标签中,由于Render Tree是由DOM树和CSSOM树组合成的,html页面需要等到CSS解析完后才能完成渲染,所以CSS应放在head标签内,优先下载解析。
- JS应该放在body的底部,因为浏览器需要一个稳定的dom树结构,而且js中很有可能有代码直接改变了dom树结构,浏览器为了防止出现js修改dom树,需要重新构建dom树的情况,所以就会阻塞其他的下载和呈现。
解释白屏和FOUC
白屏和无样式内容闪烁(FOUC)是由于不用浏览器加载显示页面的机制不同造成的。当把CSS样式放在底部或者使用@import方式引入样式时,一些浏览器例如chrome,它的加载和渲染机制是等CSS全部加载解析完成后再渲染展示页面,而这个等待的时间就是白屏。另外一些浏览器,如Firefox,它会在CSS未加载前展示页面,等CSS加载后再重新绘一次,这就造成了FOUC(无样式内容闪烁)。如果把JS文件放在头部,脚本会阻塞后面内容的展示和其后组件的下载,也会导致白屏现象。
async和defer的作用是什么?有什么区别
当浏览器遇到script脚本的时候:
蓝色线代表网络读取,红色线代表执行时间,这俩都是针对脚本的;
绿色线代表 HTML 解析。
此图告诉我们以下几个要点:
- a. defer 和 async 在网络读取(下载)这块儿是一样的,都是异步的(相较于 HTML 解析)
- b. 它俩的差别在于脚本下载完之后何时执行,显然defer 是最接近我们对于应用脚本加载和执行的要求的c. 关于 defer,此图未尽之处在于它是按照加载顺序执行脚本的,这一点要善加利用
- c. async 则是一个乱序执行的主,反正对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行e. 仔细想想,async 对于应用脚本的用处不大,因为它完全不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的,最典型的例子:Google Analytics
简述网页的渲染机制
- Create/Update DOM And request css/image/js:浏览器请求到HTML代码后,在生成DOM的最开始阶段(应该是Bytes → characters后),并行发起css、图片、js的请求,无论他们是否在HEAD里。注意:发起js文件的下载request并不需要DOM处理那个script节点。比如:简单的正则匹配就能做到这一点,虽然实际上并不一定是通过正则。这是很多人在理解渲染机制的时候存在的误区。
- Create/Update Render CSSOM:CSS文件下载完成,开始构建CSSOM。
- Create/Update Render Tree:所有CSS文件下载完成,CSSOM构建结束后,和DOM一起生成Render Tree。
- Layout:有了Render Tree,浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系。下一步操作称之为layout,顾名思义就是计算出每个节点在屏幕中的位置。
- Painting:Layout之后,浏览器已经知道了哪些节点要显示(which nodes are visible)、么个节点的CSS属性是什么(their computed style)、每个节点在屏幕中的位置是哪里(geometry)。
- Painting,按照算出来的规则,通过显卡,把内容画到屏幕上。以上五个步骤前3个步骤之所有使用 “Create/Update” 是因为DOM、CSSOM、Render Tree都可能在第一次Painting后又被更新多次,比如JS修改了DOM或者CSS属性。Layout 和 Painting 也会被重复执行,除了DOM、CSSOM更新的原因外,图片下载完成后也需要调用Layout 和 Painting来更新网页。