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

传统的浏览器,对于静态资源加载,会阻塞 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() 去加载静态资源,我们可以做出什么优化?

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

如下

	<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转圈状态。

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

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

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

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

结果是:

关于document.write()加载JS等静态资源 和 异步async加载JS的更多相关文章

  1. 使用Node.js搭建静态资源服务器

    对于Node.js新手,搭建一个静态资源服务器是个不错的锻炼,从最简单的返回文件或错误开始,渐进增强,还可以逐步加深对http的理解.那就开始吧,让我们的双手沾满网络请求! Note: 当然在项目中如 ...

  2. springboot 项目中css js 等静态资源无法访问的问题

    目录 问题场景 问题分析 问题解决 问题场景 今天在开发一个springboot 项目的时候突然发现 css js 等静态资源竟然都报404找不到,折腾了好久终于把问题都解决了,决定写篇博客,纪录总结 ...

  3. js加载超时 nginx静态资源

    server { listen ; server_name www.example.com; client_max_body_size 20M; root /xxx/xxx;//项目路径 locati ...

  4. 解决Tomcat无法加载css和js等静态资源文件

    解决思路有两个 一是,你使用了Apache服务器,html不交给Tomcat处理,所以你找不到Html等静态资源,所以你先停掉阿帕奇,然后只用Tomcat猫试试. 二是,像我一样,使用了Jetty开发 ...

  5. WKWebView实现网页静态资源优先从本地加载

    前言:最近微信的小游戏跳一跳特别的火,顺便也让h5小游戏更加的火热.另外微信小程序,以及支付宝的小程序都是用H5写的.无论是小游戏还是小程序,这些都需要加载更多的资源文件,处理更多的业务.这些都对网页 ...

  6. spring boot入门笔记(四) - 多环境配置、加载顺序、静态资源映射

    1.多环境配置 先描述下以前的开发流程:从SVN把项目下载到本地,各种修改配置文件,启动成功:完成功能后上传到公司的测试服务器,修改各种配置文件,启动成功:最后到上线的日子里,把新功能中涉及到的文件打 ...

  7. spring项目加载不出来静态资源

    方法1: 拦截器中增加针对静态资源不进行过滤(涉及spring-mvc.xml) <!-- 添加注解驱动 --> <mvc:annotation-driven/> <!- ...

  8. 使用r.js优化静态资源

    r.js主要功能:优化项目的静态资源.可以简化压缩代码,减少体积.指定模块将多个组件合并为一个文件,减少HTTP请求数量.具体使用步骤如下: 先把 r.js 文件放到项目根目录,再于项目根目录内新建一 ...

  9. NodeJS + express访问html、css、JS等静态资源文件

    原先做前端开发时都是用XAMPP或LAMP,把HTML.CSS.JS等前端资源放到htdocs下,测试自己的前端代码,但有些不方便的地方是,在调用Ajax请求后无法模拟请求返回的数据,最近学了点Nod ...

随机推荐

  1. mybatis ${}使用注意事项

    ${key}有值, ${key,jdbcType=VARCHAR}没有值 总结:${}使用时不要指定jdbcType等属性,指定这些反而取不到值,这也是跟#{}的一个区别.以上只是开发中遇到的情况,具 ...

  2. Windows 如何查看本地端口被进程占用的情况?

    1.查看端口占用情况: 1.开始--运行--cmd 进入命令提示符. 2. 输入netstat -ano(或netstat -nao) ,即可看到所有进程(这里显示进程的PID)占用端口的情况. 3. ...

  3. June 26th 2017 Week 26th Monday

    I am a little tempted, but so afraid to look in your eyes. 我对你有一点动心,却如此害怕看你的眼睛. Now that you are tem ...

  4. RabbitMQ的事件总线

    RabbitMQ的事件总线 在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容.下面的类图描述了我们已经实现的组件及其之间的关系,貌似系 ...

  5. IOS 上传下载

    下载地址:https://github.com/samsoffes/ssziparchive 注意:需要引入libz.dylib框架 // Unzipping NSString *zipPath = ...

  6. Windows环境双系统安装环境配置

    (最惊喜的事情莫过于...在安装系统完成重新试图安装Docker时解决了关于HyperV的问题,结果提示Docker只能在Win10 Pro或者Enterprise环境下运行...我很坚强...可以按 ...

  7. create-react-app部署到GitHub Pages时报错:Failed to get remote。origin.url

    最近使用create-react-app脚手架开发了一个私人博客:点击跳转,在部署到GitHub Pages的时候报了一个错误,具体如下: 在create-react-app的GitHub库的issu ...

  8. was缓存以致web.xml更改无效

    was缓存导致web.xml更改无效 在项目中经常遇见这样的问题:修改应用的配置文件web.xml后,无论重启应用还是重启WebSphere服务器,都不能重新加载web.xml,导致修改的内容无效. ...

  9. sqlite3如何退出...>状态

    一般是进入SQL数据语言模式了,此时要想退出...>状态,只要输入一条完整的SQL语句就行了,也就是末尾要加上:(分号)这个符号就可以退回到sqlite>状态

  10. FastJSON使用列子

    一.介绍: 前一段时间使用FastJSON对前台传入的数据进行处理,数据格式为JSONObject存入到数据库的一个字段里,前台以JSONArray传给后台,在JSONArray里存放不同的对象,当部 ...