浏览器渲染Html文件过程
一. 浏览器主要渲染过程
1. 从服务器拿到Html文件代码后,浏览器在内存条开辟出一块栈内存,用来给代码执行提供环境,同时分配一个主线程去一行行的解释和执行代码
2. 代码一行行进栈执行,执行完出栈,当遇到link/script/img/video后浏览器会开辟全新的线程去加载资源文件,然后主线程继续一行行解析Html
3. 当第一次自上往下走完Html文件就生成了Dom树,这时如果有其他线程加载完资源就会回到主线程执行文件(如果其他文件一起加载完也是一个一个文件一行行解析),阻塞主线程,主线程会一行行执行这个加载完的文件
4. 当css也处理完就会生成cssom树
5. 当有dom树和cssom树就会开始渲染,并且所有文件执行完浏览器就显示出页面
二. js在渲染中的情况
没有async和defer和通常放在body尾部原因
浏览器会立即加载并执行指定的脚本,“立即”指的是js脚本立即执行阻塞其后的DOM解析,也就是说不等待后续载入的HTML元素,读到就去加载js文件并执行。这样就会造成当前js用到的dom还没解析就执行js,所以通常js放在body内的最后一行保证dom都被解析了
MDN解释:为了防止js出错,调用还未解析的dom
w3c提示:
把脚本置于 <body> 元素的底部,可改善显示速度,因为脚本编译会拖慢显示。
当js加上async(脚本执行顺序是按照下载完成的先后顺序)
1.浏览器开始解析网页
2.解析过程中,发现带有async属性的script标签
3.浏览器继续往下解析 HTML 网页,同时并行下载外部脚本
4.脚本下载完成,浏览器暂停解析网页,开始执行下载的脚本
5.脚本执行完毕,浏览器恢复解析网页
当js加上defer(脚本执行顺序是按照出现的先后顺序)
1.浏览器开始解析网页
2.解析过程中,发现带有defer属性的脚本元素
3.浏览器继续往下解析网页,同时并行下载脚本元素加载的外部脚本
4.浏览器完成解析网页,此时再回过头执行已经下载完成的脚本
注意:选择async还是defer,两者之间的选择是看脚本之间是否有依赖关系,有依赖的话应当要保证执行顺序,应当使用defer,
没有依赖的话使用async。