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

传统的浏览器,对于静态资源加载,会阻塞 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. Bootstrap + AngularJS+ Ashx + SQL Server/MySQL

    去年年底12月,为适应移动端浏览需求,花了1个月时间学习Bootstrap,并将公司ASP网站重构成ASP.NET. 当时采取的网站架构: Bootstrap + jQuery + Ashx + SQ ...

  2. 完美解决Office2003、Office2007、Office2010、Office2013共存方法

    原文:http://www.360doc.com/content/14/0903/16/7555793_406799011.shtml 微软Office深受广大用户的青睐,特别是经典的Office 2 ...

  3. linux 获取当前程序路径

    const std::string strCfgName = "logger_import_db.conf" ;bool fGetCfgFileName(std::string&a ...

  4. pymsql模块使用

    数据库连接客户端 链接:https://pan.baidu.com/s/1pM0h4SV 密码:614v  sql指令基本用法:

  5. gradle中文学习资料

    http://wiki.jikexueyuan.com/project/GradleUserGuide-Wiki/ https://www.gitbook.com/book/lippiouyang/g ...

  6. nodejs + redis/mysql 连接池问题

    nodejs + redis/mysql 连接池问题 需不需要连接池 连接池的作用主要是较少每次临时建立连接所带来的开销.初步一看,nodejs运行单线程上,它不能同时使用多个连接,乍一看是不需要连接 ...

  7. Linux 服务器性能问题排查思路

    一个基于 Linux 操作系统的服务器运行的同时,也会表征出各种各样参数信息.通常来说运维人员.系统管理员会对这些数据会极为敏感,但是这些参数对于开发者来说也十分重要,尤其当你的程序非正常工作的时候, ...

  8. Apache PredictionIO在Docker上的搭建及使用

    1.Apache PredictionIO介绍 Apache PredictionIO 是一个孵化中的机器学习服务器,它可以为为开发人员和数据科学家创建任何机器学习任务的预测引擎.官方原文: Apac ...

  9. Cocos2d-x移植Android 常见问题处理办法

    1.函数.变量出现"could not be resolved "问题 出现此问题通常是没有找到cocos2d-x声明的头文件.在eclipse将cocos2d的头文件文件夹引入. ...

  10. UVa 1262 - Password(解码)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...