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 ...
随机推荐
- 更好的在 Git 项目中保存大文件(Git LFS 的使用)
珠玉在前, 大家可以参考 Git LFS的使用 - 简书 为什么要用 Git LFS 原有的 Git 是文本层面的版本控制, 为代码这种小文件设计的, 保存大文件会导致 repo 非常臃肿, push ...
- maven插件之maven-surefire-plugin,junit单元测试报告和sonar测试覆盖率的整合说明
POM中配置的如下: <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId> ...
- 【JVM】垃圾收集器和收集器的选择策略
前言:新生代的收集器有:Serial,ParNew,Parallel Scavenge等.老年代有:CMS,SerialOld,Paraller Old等.接下来将深入理解各个垃圾收集器的原理,以及它 ...
- .Net Core 使用 Swagger 提供API文档
1.运行环境 开发工具:Visual Studio 2017 JDK版本:.NET Core 2.0 项目管理工具:nuget 2.GITHUB地址 https://github.com/nbfujx ...
- LUOGU P3759 [TJOI2017]不勤劳的图书管理员(树套树)
传送门 解题思路 和以前做过的一道题有点像,就是区间逆序对之类的问题,用的是\(BIT\)套权值线段树,交换时讨论一下计算答案..跑的不如暴力快.. 代码 #include<iostream&g ...
- LOJ 2304 「NOI2017」泳池——思路+DP+常系数线性齐次递推
题目:https://loj.ac/problem/2304 看了各种题解…… \( dp[i][j] \) 表示有 i 列.第 j 行及以下默认合法,第 j+1 行至少有一个非法格子的概率,满足最大 ...
- [CSP-S模拟测试76]题解
咕咕咕 A.序列 无解情况:$n>a*b$或$n<a+b-1$ 把序列分成B段,每段内部上升,各段分界处构成下降子序列. 实现并不是太简单,要动态地考虑一下边界什么的. #include& ...
- mybatis Invalid bound statement (not found)错误解决办法
由于新版的IntelliJ IDEA不再编译source folder下的xml文件,而我们平时使用mybatis时,习惯于将*Mapper.xml文件放在与dao层.service层平级的src目录 ...
- 干货 | Bokeh交互式数据可视化快速入门
Bokeh简介 Bokeh是一款交互式可视化库,在浏览器上进行展示. Bokeh可以通过Python(或其它语言),快速便捷地为大型流数据集提供优雅简洁的高性能交互式图表. 安装 在python中有多 ...
- docker 提示 Drive has not been shared 错误
Creating laradock_docker-in-docker_1 ... Creating laradock_docker-in-docker_1 ... error ERROR: for l ...