目录
加载与执行
多数浏览器使用单一进程来处理用户界面【UI】刷新和JS代码执行,所以同一时刻只能做 一件事。JS执行过程耗时越久,浏览器等待响应的时间就越长。
脚本位置
这意味着每次<script>出现都会霸道的让页面等待脚本解析和执行。
这也是为什么建议将脚本放在body底部而不是head标签里,防止下载解析运行js脚本阻塞渲染页面,前者可能出现的情况就是页面刚开始是一片空白。
组织脚本
在无特殊处理的情况下,每一个<script>标签都会阻塞页面渲染,所以大部分情况下减少页面包含的<script>标签有助于改善这种情况。这种不只是针对外链脚本,内嵌的<script>标签存在桐言的情况,虽然不用去下载,但是执行脚本仍然会造成整体加载延时。
所以,我们可将一些较小的脚本合并为一个整体的文件。4个2k的文件与一个8k的脚本文件,同样网络条件的情况下,一定是8k的脚本文件加载更快,因为4个小文件会有更多的http请求,额外的HTTP请求一定会带来性能开销。
无阻塞的脚本
但是现在web功能越来越丰富,不可能所有的文件都集合在一个单独的文件里面,如果单独的文件特别大,那么浏览器仍然会阻塞很长一段时间,所以需要异步的加载js文件,先加载必需的js文件,然后向页面逐步加载Javascript文件。
延迟脚本
html4 为<script> 标签提供了扩展属性 defer, 带有defer属性的javascript文件下载时,它不会阻塞浏览器的其他进程,这类文件可以与页面的其他资源并行下载。下载完成之后不会立即执行,直到DOM加载完成(onload事件被触发之前)。
html5 新增了一个async扩展属性,与defer一样,可以与其他资源并行下载,不会阻塞其他浏览器进程,但是执行时机有一点不一样,async是加载完成之后立即执行,defer是等待页面dom加载完成之后再执行。
参考下面的图(source :https://html.spec.whatwg.org/multipage/scripting.html#attr-script-defer)
动态脚本
动态的创建script标签 【document.createElement('script')】 ,这种情况,下载和执行都不会阻塞页面其他进程。
ajax请求脚本内容,然后动态创建script标签,然后赋予内容,这种对比上面的好处就是,下载完成之后不立即执行,可以控制到特定的流程之后再执行。
参考资料:
《高性能javascript》第一章
https://html.spec.whatwg.org/multipage/scripting.html#attr-script-defer
https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/script