JS的加载和执行
从JS的加载和执行谈性能优化
---高性能JS读后感(第一章)
从脚本的"霸道"说起,随着浏览器的进步,js越来越听话了,所以,我们先说说以前的浏览器是怎么加载js的,以及js如何个霸道法.
1.阻塞的脚本
在以前,js很霸道.
问:当我们在网页中使用<script></script>时,到底发生了什么?
答:无论是内嵌的<script>标签代码还是用<script>引入文件,当浏览器解析到<script>元素时,浏览器就会去加载js内容,这时,页面的其他资源的加载和渲染都会停止,可以说<script>元素是老大,当他说话(加载)时,其他人都不敢说(其他资源都会停止加载和渲染),这就是我们常说的js会阻塞资源加载和页面渲染.这是<script>的霸道(特点).单加载就阻塞了,执行就更不用说了.
所以,我们一般把js放在页面的底部,</body>之前,这样当页面加载到底部的js时,页面的结构和渲染都完成了,这个时候你阻塞也不影响我页面的加载.
后来浏览器开始进步
当浏览器解析到<script>元素时,依旧会阻塞页面其他资源的加载(比如图片)和渲染(css的渲染),但是如果页面有多个<script>,就是说如果我们引入两份js文件,那么这两份js文件是可以并行加载的,不用像之前一样,得第一份加载完再去加载第二份.
浏览器继续进步
2.无阻塞的脚本
无阻塞脚本的秘诀在于,在页面加载完成后才加载js代码.就是说在window对象的load事件触发后再下载脚本.
无阻塞脚本之延迟的脚本(这里的延迟指的是延迟执行,而不是延迟加载)
在现在的主流浏览器,js的加载已经不会阻塞页面了,他能够与其他资源和平共处,就是说他越来越乖巧了,当他在加载时,他允许图片等其他资源的加载,当然执行的话还是会阻塞的.
如下图,js与图片并行加载.(主流浏览器)

js的加载说完了,我们说说js的执行.
问:js执行为什么会阻塞页面的渲染.
答:js在执行时,一般都会操作DOM,操作DOM就会影响到DOM树的渲染,所以js的执行肯定会阻塞渲染.
注意:js是单线程,但浏览器是多线程,js在执行时,DOM树在构建,同时渲染树也在渲染,这个时候如果js构建和浏览器即将渲染的是同一个节点怎么办?所以,为免冲突,js在执行时,停止渲染.
现在js的加载和执行略懂略懂,那么问题来了.
问:js放置的最优位置的底部,我现在有一份js必须在head,等页面结构加载完(window.onload)就马上执行,就是说我要先加载后执行,那么我该怎么办?
答:用defer,在<script>加上defer属性
<script type="text/javascript" src="jquery-1.8.3.min.js" defer></script>
defer的功能:指明本元素所含的脚本不会修改DOM,(即只加载不执行),因此代码能安全的延迟执行.阻塞的脚本变成延迟的脚本了.
问:我现在有一份js必须在head,想让它加载完马上执行怎么办?
答:用async,在<script>加上async属性
<script type="text/javascript" src="jquery-1.8.3.min.js" async></script>
async的功能:异步并行加载js,加载完之后立即执行.defer是加载后等页面加载后再执行,两者的区别是执行方式的不同.
问:我们什么时候用defer,什么时候用async?
答:
1.当js并不需要立马加载的时候,我们把js放在页面底部就可以了,不需要用到这两个属性.
2.当某段js需要立马加载时,判断其是否需要立即执行,需要就用async,不需要立即执行就用defer.
当然,这里需要强调下,js立即执行,这个时候是会阻塞页面的渲染的.
也需要考虑到,这两个属性的浏览器支持情况,在不支持这两个属性的浏览器上,其实他们是会阻塞页面的渲染的(不支持的情况下,加载js不阻塞,但是加载完后的js会去立马执行,这个时候就会阻塞了).
3.DOM树创建完并不意味着页面资源加载完,所以在DOM树创建完,触发window.onload的时候,中间还是有一点时间的,这个时间就是加载其他资源的时间.(比如说加载js)
4.其实,在不考虑多个js文件有多个http请求数的情况下,当你把js放在页面底部的时候,其实已经是一种无阻塞的脚本了.
总结:(摘自书中内容)
减少js对性能的影响:
1.</body>闭合标签之前,将所有的<script>标签放到页面底部.这能确保在脚本执行前页面已经完成了渲染.
2.合并脚本.页面的中的<script>标签越少,加载也就越快,响应也更迅速.无论外链文件还是内嵌脚本都是如此.
3.有多种无阻塞下载js的方法:(可自行搜索用法)
- 使用<script>标签的defer属性
- 使用动态创建的<script>元素来下载并执行代码
- 使用XHR对象下载js代码并注入页面中
个人觉得,在目前,js模块加载器,js模块打包器都有,解决文件的依赖关系并且打成一个包是比较容易的,再把打成的包放到</body>,可以减少http请求,也不会阻塞页面加载和渲染(可以说这是一个无阻塞的脚本),虽然这个文件可能很大,但相对于减少了http请求数来说,还是利大于弊的,因为我们一个页面不打包可能有很多个js,这样请求数会很多.
当然对于一些库,我们可以单独引入,这样可以缓存起来,缓存起来的文件加载就更快了.
有错请指出,欢迎交流~
JS的加载和执行的更多相关文章
- JS 动态加载脚本 执行回调
JS 动态加载脚本 执行回调 关于在javascript里面加载其它的js文件的问题可能很多人都遇到过,但很多朋友可能并不知道怎么判断我们要加载的js文件是否加载完成,如果没有加载完成我们就调用文件 ...
- 性能优化-css,js的加载与执行
前端性能优化 css,js的加载与执行 javascript是单线程的 一个网站在浏览器是如何进行渲染的呢? html页面加载渲染的过程 html渲染过程的一些特点 顺序执行,并发加载 词法分析 并发 ...
- JS 动态加载脚本 执行回调_转
关于在javascript里面加载其它的js文件的问题可能很多人都遇到过,但很多朋友可能并不知道怎么判断我们要加载的js文件是否加载完成,如果没有加载完成我们就调用文件里面的函数是不会成功的.本文讲解 ...
- JS脚本加载与执行对性能的影响
高性能JavaScript-JS脚本加载与执行对性能的影响 在web产品优化准则中,很重要的一条是针对js脚本的加载和执行方式的优化.本篇文章简单描述一下其中的优化准则. 1. 脚本加载优化 1.1 ...
- 前端性能优化 css和js的加载与执行
一个网站在浏览器端是如何进行渲染的? html本身首先会被渲染成 DOM 树,实际上 html 是最先通过网址请求过来的,请求过来之后,html 本身会由一个字节流转化成一个字符流,浏览器端拿的就是字 ...
- 高性能javascript学习笔记系列(1) -js的加载和执行
这篇笔记的内容主要涉及js的脚本位置,如何加载js脚本和脚本文件执行的问题,按照自己的理解结合高性能JavaScript整理出来的 javascript是解释性代码,解释性代码需要经历转化成计算机指令 ...
- js并行加载,顺序执行
js并行加载,顺序执行 <script>运行脚本或加载外部文件时,会阻塞页面渲染,阻塞其他资源的加载.如果页面中需要加载多个js文件,在古老浏览器中性能会比较糟糕. 因此有了最原始的优化原 ...
- jquery js 动态加载 js文件
jquery方法 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...
- 使用getScript()方法异步加载并执行js文件
使用getScript()方法异步加载并执行js文件 使用getScript()方法异步请求并执行服务器中的JavaScript格式的文件,它的调用格式如下所示: jQuery.getScript(u ...
随机推荐
- Prometheus指标采集常用配置
一.node-exporter配置textfile收集器 textfile收集器作用: 运行暴露自定义指标.例如,需要在某个被监控节点上添加一个地理位置的指标. node-exporter会自动启动t ...
- centos 6.5 解压 tar.gz
只查看 tar.gz 文件内容而不解压 tar -tvf filename.tar.gz 解压为 tar 文件 gzip -d filename.tar.gz 解压为文件或目录 tar xvf fil ...
- Ubuntu16.04安装x11VNC远程桌面
1. 安装x11vnc sudo apt-get install x11vnc 2. 设置密码 x11vnc -storepasswd 3. 修改配置文件 sudu vim /lib/systemd/ ...
- Sublime Text 注册及使用相关
sublime text3 注册码 2019-07-01 注册码可以直接用 地址: 2019-07-01 亲测可用 2019-07-18 亲测可用 -– BEGIN LICENSE -– Die So ...
- 【leetcode】436. Find Right Interval
题目如下: 解题思路:题目要求的是对于任意一个区间i,要找出一个区间j,使得j的起点最接近i的终点.既然这样,我们可以把所有区间的终点组成一个列表,并按大小排序,使用二分查找就可以快速找到j区间.注意 ...
- Servlet 第一天
package com.servlet; import java.io.IOException; import javax.servlet.Servlet; import javax.servlet. ...
- [CF1168D]Anagram Paths
题意:给一棵\(n\)个节点的二叉树,每条边上有一个小写字母或者\(?\),\(q\)次修改操作,每次修改某条边上的字符,问修改后是否存在一种方案,使得给所有\(?\)填上小写字母后,所有叶子到根的路 ...
- linux nfs文件共享
◆一.概念 NFS是网络文件系统(Network File System)的简称,是分布式计算机系统的一个组成部分,可实现在异构网络上共享和装配远程文件系统. NFS由SUN公司开发,目前已成 ...
- docker 应用
在ubuntu安装docker 编写Dockerfile (用来操作容器) FROM java:8 #获取java官方镜像 jdk版本为1.8 VOLUME /tmp # 数据存储目录,容器退出后数据 ...
- 2015年6月发布了ECMAScript6版本
2015年6月 node.js.npm | cnpm.cli angular2.x.react.js.Vue.js