关于document.write()加载JS等静态资源 和 异步async加载JS

现流行浏览器对于静态资源的预加载

传统的浏览器,对于静态资源加载,会阻塞 HTML 解析器的线程进行,不管内联仍是外链。
例如:html

<script src="test1.js"></script>
    <script src="test2.js"></script>
    <script src="test3.js"></script>
    <img src="img.png" />

传统浏览器HTML解析器,会从test1.js 逐一解析到img.png,只个解析过程是同步的,只有当test1.js解析加载完成才会到test2.js 顺序加载。假设js文件加载时间须要1秒,img文件也须要1秒的时间,那么除去页面其余阶段的render时间不计,img图片会是4秒以后才显示给用户。前端

然而,如今主流浏览器对于静态资源的解析,已经作到了预解析和预加载。

相比传统浏览器,当浏览器HTML解析器,遇到test1.js静态资源的是,主线程中的解析器暂停解析,浏览器会新开启一个解析器线程,去预加载后面的资源。假设js文件加载时间须要1秒,img文件也须要1秒的时间。当浏览器遇到第一个js文件test1.js的时候,会新开启一个解析器线程,去预加载解析其余静态资源。除去页面其余阶段的render时间不计,那么img图片只会是2秒以后才显示给用户。浏览器

但浏览器能作的仅仅是预解析和预加载,脚本的执行和 DOM 树的构建仍然必须是线性的缓存

document.write() 打破浏览器的预解析和预加载,由于document.write()加载的JS文件没法让HTML预解析器发现

<script src="test1.js"></script>
    <script>
        document.write('<script src="http://xxx.com/test2.js"><\/script>')
    </script>
    <script src="test3.js"></script>

这个例子中,因为 test2.js 是经过 JS 代码插入的,HTML 预解析器是看不到的,因此只有当 test1.js 下载并执行完毕,且第二个内联的 script 执行完毕后,test2.js 才会开始下载,也就是说,test2.js 不能和 test1.js 及 test3.js 并行下载了,从而致使页面展示变慢,一样假设每一个文件的下载时间都是 1 秒,那么这三个文件下载执行完就须要两秒,就由于 test2.js 不能预加载。在一个外链的 JS 文件好比 a.js 中执行 document.write("<script...) 也是相似的效果。异步

针对document.write() 去加载静态资源,咱们能够作出什么优化?

将资源转成外链的方式加载。
以下async

<script src="test1.js"></script>
    <script>
        document.write('<script src="http://xxx.com/test2.js"><\/script>')
    </script>
    <script src="test3.js"></script>

改为优化

<script src="test1.js"></script>
    <script src="test2.js"></script>
    <script src="test3.js"></script>

尽量,让浏览器预解析器发现静态资源文件。可是这并不意味着页面的加载时间会大大减小。
假设test1.js的加载时间为1秒,test2.js的加载时间为10秒。即使test1.js以后的静态资源参与了浏览器的预解析加载,为了配合这句话“但浏览器能作的仅仅是预解析和预加载,脚本的执行和 DOM 树的构建仍然必须是线性的”。页面始终会所有资源加载完以后才完成渲染,test2.js的10秒加载时间仍旧会让页面处于loading转圈状态。spa

对于非第三方的静态资源的加载时间太长,应考虑前端资源的优化,这里列出来可能多的优化方案,可是暂不作详解线程

  • 减小静态文件的文件大小 (代码压缩)
  • 减小静态文件请求数量 (文件合并)
  • gzip
  • CDN和缓存

对于第三方的静态资源文件,可使用async实现异步加载code

async 加载静态资源

一句话归纳即是异步的 script 根本不会阻塞 HTML 解析器,也就用不到预解析了
目前大部分第三方库都会支持async 异步 加载JS资源,而后去调用一个全局function 例如

<script src="test.js?callback=dosomething" async ></script>

async 的js资源,若是长时间pedding 会影响onload加载时间

关于document.write()的其余知识点

ducument.write 在onload以前,插入执行document.write()都会给页面插入内容,页面onload完成以后,浏览器输出流自动关闭;在此以后,任何一个对当前页面进行操做的document.write()方法将打开—个新的输出流

以下

结果是:

页面onload完成以后,调用document.write

结果是:

相关文章
相关标签/搜索