《高性能JavaScript》读书笔记(一)

《高性能JavaScript》这本书很多人推荐,我对这本书的印象也是值得学习前端的童鞋的细读吸收。作为学习者,同样也是要认真的学习这本书中为我们总结的一些开发中的经验,能提高我们开发代码的效率。

第一章主要针对JavaScript的加载跟执行的优化。总结一下就是推迟加载JavaScript代码,减少JavaScript文件加载数量及异步加载JavaScript代码。

优化加载JavaScript代码的原因

一般我们在入门前端初期,都会学到,<head>标签中可以放<script>标签,用来引入js文件或js代码。然后大部分人都会习惯性的把js代码从<head>标签引入。

操作上是正确的,确实可以完成js代码的引入,但是由于js代码具有阻塞的特性,会影响页面的解析与加载时间。一般页面的加载,首先会HTML代码的<head>标签开始。当代码执行到<head>标签的<script>标签时,由于浏览器无法判断<script>标签中的代码是否会影响DOM节点,所以会暂停页面的加载,而优先执行<script>标签中的代码。

如果<script>标签的代码是直接出现在标签中,则直接执行;而如果是通过引入的方式,则还需要下载之后再执行。一旦下载的文件较大,加上加载的时间,那将让网页的客户体验很糟糕。

于是,就有了优化加载JavaScript代码的必要。从上面我们可以看到,一般可以优化的方案,就是把下载JavaScript文件的时间推迟,或者把执行JavaScript代码的时间推迟。下面我们就来总结一下优化的方案

加载JavaScript代码优化的方案

阻塞问题的优化

之所以会阻塞,就是因为JavaScript代码早于html的DOM代码执行了,再进一步说,因为JavaScript代码在<head>标签中,比<body>标签更早被获取,所以才会有阻塞的问题。因此,可以考虑让JavaScript代码被滞后获取。

最简单的想法就是把 <script>标签放到<body>标签底部 ,这样可以减少对页面渲染的阻塞。这个也是目前开发中比较常见的一种优化方案。

1
2
3
4
5
6
7
8
9
10
11
<html>
<head>
<title>Example</title>
<link rel="stylesheet" type="text/css" herf="style.css">
</head>
<body>
<p>Hello World</p>

<script type="text/javascript" src="file1.js"></script>
</body>
</html>

同样也要一种类似的方案,就是通过给 <body>标签创建<script>标签,再引入js文件 的方案。这个方案看起来比上面的方案复杂了,但是在需要引入多个js文件的情况下,还是比较好的方案。

1
2
3
4
var script = document.createElement("srcipt");
script.type = "text/javascript";
script.src = "file1.js";
document.getElementsByTagName("head")[0].appendChild(script);

另一种方案则是采用了 XMLHTTPRequest脚本注入 ,先创建一个XHR对象,然后用这个对象下载js文件,然后再通过创建<script>元素把js代码引入到页面中。

这种方案的优点就是可以下载JavaScript代码但不会立即执行,而且所有主流浏览器都能正常工作。但是也会有一个问题,就是因为涉及异步请求文件,所以需要遵循同域。

1
2
3
4
5
6
7
8
9
10
11
12
13
var xhr = new XMLHttpRequest();
xhr.open("get", "file1.js", "true);
xhr.noreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status >= 200 & xhr.status < 300 || xhr.status == 304) {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = xhr.responseText;
document.body.appendChild(script);
}
}
};
xhr.send(null);

在《高性能JavaScript》的后面《推荐的无阻塞模式》一节中也是对这个方案做了封装,使这个方案适合添加大良的JavaScript代码。

加载JavaScript的优化

一般一个项目加载JavaScript文件都会有好几个文件(特别是强调模块化工程化的前端开发),如果遇到一个HTML页面需要加载多个js文件,则每个js文件都会需要单独的下载跟执行,会影响页面的总体性能。因此,书中提及了雅虎提供的合并处理器,可以用一个URL包含多个文件,从而使URL上的文件可以同时加载。
不过,从现在前端开发的做法上来看,虽然开发上强调模块化,但是实际已经把开发跟上线分离,实际上线的项目中,已经通过打包工具减少了文件(一般可以看到打包的js文件就剩一个bound.js了),所以书中的这个方案可以说已经通过工程化得到更好更广泛的解决了。

执行JavaScript的优化

书中也提及如何延迟js代码的执行。HTML 4为<script>标签定义了一个扩展属性:defer,这个属性主要是表明当前元素的脚本不影响DOM,所以浏览器会在页面加载完成后在执行<script>标签中的脚本。

最后

书中还提及几个库,都是针对无阻塞脚本加载开发的,这里就没在深入了解了。

总结一下,优化JavaScript代码的加载跟执行对页面的客户体验会有很大的提升。从当前前端开发来看,更多的方案是把多个js文件打包成少量的js文件,然后把<script>标签放到<body>标签底部。书中也提及了一些其他的方案,这些方案也可以在一些小项目中使用,一样能提升页面性能。

上面使用的代码示例都是书中的代码示例。