CSS和JS在网页中的放置顺序是怎样的?
css建议放在head中,js放在body的最后。
原理:
- 浏览器渲染过程是先渲染html DOM树,然后渲染css 树,最后合并显示,所以css放在头部加载。如果css放置在最后,就可能会出现白屏(chrome等浏览器)或闪屏效果(firefox浏览器)
- 同样根据浏览器的渲染方式来看,js的渲染方式是先加载,然后立即执行。而JS会阻塞文档内容的渲染呈现,阻塞后面的资源加载,所以如果放头部或者比较前面,就也可能会出现白屏情况,所以等html和css都加载渲染完之后,再执行js的加载,这样就不容易出现问题了。而且js的作用主要也是用来与页面上的内容做交互的,所以等页面内容渲染完之后,才能正确的操作元素。
解释白屏和FOUC
要了解白屏和FOUC,就要先了解浏览器的渲染机制。
上图是两种不同浏览器内核的渲染过程,两者有略微的不同,总体是相同的。两者的不同也就是造成了FOUC(Flash of Unstyled Content 无样式内容闪烁)的出现。
浏览器渲染流程:
- 首先,浏览器接到一个页面请求,然后开始加载html代码,构建DOM Tree, 并且DOM Tree的构建过程是一个深度遍历过程:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点。
- 下载css文件,解析css并构建css Rule tree
- 根据DOM Tree 和css Rule tree合并渲染并构建一个Render tree
- 然后浏览器再根据样式中的布局layout节点位置信息,最后绘制呈现页面
firefox用的内核渲染方式是先加载渲染出DOM Tree,然后再加载解析css,这两步不是并行的,之后再把css样式绘制到DOM Tree上,此时浏览器再重新绘制一遍DOM tree。
以上可以看出浏览器的工作流程主要是从上到下的渲染方式,这样问题就来了,当我们把css文件放在比较后面的位置,当网络加载比较慢或者第一次打开网页没有缓存的情况下,就可能出现浏览器在拼命的加载html和css,构建树,css又在最后,浏览器找css找的好累,还要等css解析完才能最后合并绘制,那么这时,浏览器可不就白屏了嘛。。
FOUC呢,就避免了白屏的尴尬,但是因为先构建的DOM树,css还没来得及解析,那就会出现因为没有css样式而开始比较难看的画面了。。之后等css解析好了之后,再重新绘制一遍整个页面,这样我们就会看到一闪而过的无样式画面。
async和defer的作用是什么?有什么区别
由于js的加载会阻塞文档的渲染和其他的加载,并且立即执行。所以出现了async和defer。async和defer的作用都是可以将script实现异步加载。但是有些许不同。
async:
- 用于异步下载脚本文件,下载完毕立即解释执行代码。
- 如果有多个声明了async的脚本,其下载和执行也是异步的,不能确保彼此的先后顺序
- async会在load事件之前执行,但并不能确保与DOMContentLoaded的执行先后顺序
defer:
- 用于开启新的线程下载脚本文件,并使脚本在文档解析完成后执行。
- 如果有多个声明了defer的脚本,则会按顺序下载和执行
- defer脚本会在DOMContentLoaded和load事件之前执行
注:如果加载的js有先后依赖关系,则要用defer来保证执行顺序。