关于document.write()加载JS等静态资源 和 异步async加载JS
现流行浏览器对于静态资源的预加载
传统的浏览器,对于静态资源加载,会阻塞 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的更多相关文章
- 使用Node.js搭建静态资源服务器
对于Node.js新手,搭建一个静态资源服务器是个不错的锻炼,从最简单的返回文件或错误开始,渐进增强,还可以逐步加深对http的理解.那就开始吧,让我们的双手沾满网络请求! Note: 当然在项目中如 ...
- springboot 项目中css js 等静态资源无法访问的问题
目录 问题场景 问题分析 问题解决 问题场景 今天在开发一个springboot 项目的时候突然发现 css js 等静态资源竟然都报404找不到,折腾了好久终于把问题都解决了,决定写篇博客,纪录总结 ...
- js加载超时 nginx静态资源
server { listen ; server_name www.example.com; client_max_body_size 20M; root /xxx/xxx;//项目路径 locati ...
- 解决Tomcat无法加载css和js等静态资源文件
解决思路有两个 一是,你使用了Apache服务器,html不交给Tomcat处理,所以你找不到Html等静态资源,所以你先停掉阿帕奇,然后只用Tomcat猫试试. 二是,像我一样,使用了Jetty开发 ...
- WKWebView实现网页静态资源优先从本地加载
前言:最近微信的小游戏跳一跳特别的火,顺便也让h5小游戏更加的火热.另外微信小程序,以及支付宝的小程序都是用H5写的.无论是小游戏还是小程序,这些都需要加载更多的资源文件,处理更多的业务.这些都对网页 ...
- spring boot入门笔记(四) - 多环境配置、加载顺序、静态资源映射
1.多环境配置 先描述下以前的开发流程:从SVN把项目下载到本地,各种修改配置文件,启动成功:完成功能后上传到公司的测试服务器,修改各种配置文件,启动成功:最后到上线的日子里,把新功能中涉及到的文件打 ...
- spring项目加载不出来静态资源
方法1: 拦截器中增加针对静态资源不进行过滤(涉及spring-mvc.xml) <!-- 添加注解驱动 --> <mvc:annotation-driven/> <!- ...
- 使用r.js优化静态资源
r.js主要功能:优化项目的静态资源.可以简化压缩代码,减少体积.指定模块将多个组件合并为一个文件,减少HTTP请求数量.具体使用步骤如下: 先把 r.js 文件放到项目根目录,再于项目根目录内新建一 ...
- NodeJS + express访问html、css、JS等静态资源文件
原先做前端开发时都是用XAMPP或LAMP,把HTML.CSS.JS等前端资源放到htdocs下,测试自己的前端代码,但有些不方便的地方是,在调用Ajax请求后无法模拟请求返回的数据,最近学了点Nod ...
随机推荐
- Android 最新 Support V4 包大拆分有用吗?
Google 更新了最新的 Support Library 版本,其中最为显眼的功能莫过于 support-v4 大拆分,然后这个拆分现在看来并没有那么美好. v4 包从 2011 年开始引入,包含 ...
- Mysql 启动失败常见错误
各位可以按照顺序逐条拍错. mysql启动时报错:Starting MySQL... ERROR! The server quit without updating PID file (/opt/my ...
- 爬虫入门之反反爬虫机制cookie UA与中间件(十三)
1. 通常防止爬虫被反主要有以下几个策略 (1)动态设置User-Agent(随机切换User-Agent,模拟不同的浏览器) 方法1: 修改setting.py中的User-Agent # Craw ...
- July 04th 2017 Week 27th Tuesday
Nothing is really beautiful but truth. 只有真理才是真美. Truth can be beautiful, but it also can be cruel. W ...
- February 21 2017 Week 8 Tuesday
To make each day count. 让每一天都物有所值. We always want to make our life meaningful, however, the acutal f ...
- 初窥IM通信协议
即时通讯(Instant Messenger,简称IM)软件多是基于TCP/IP和UDP进行通讯的,TCP/IP和UDP都是建立在更低层的IP协议上的两种通讯传输协议. 前者是以数据流的形式,将传输数 ...
- gulp使用方法总结
gulp是用于前端构建的基于文件流的一套工具.可以用于压缩.编译.合并.检查文件等操作.可以节省大量的用于繁琐重复操作的人力.最开始就是安装gulp工具了,在命令行中切换到工作的文件目录下,安装gul ...
- Cocos2d-x移植Android 常见问题处理办法
1.函数.变量出现"could not be resolved "问题 出现此问题通常是没有找到cocos2d-x声明的头文件.在eclipse将cocos2d的头文件文件夹引入. ...
- Spark Streamming 基本输入流(二) :Socket
Spark Streamming 可以通过socket 进行数据监听. socket的输入方可以通过nc 或者自己开发nc功能的程序. 1.系统自带的nc su root a yum install ...
- bootstrap table 解析写死的json.并且把进度条放进列中。
function showPhaseInfo(phase){ //json字符串转json对象 var phaseInfo = eval(phase); $('#phaseTable').bootst ...