performance

JavaScript的加载优化

前端开发中,JavaScript 变得越来越重要,页面载入中,JavaScript 占的比重也更高。不同与别的静态资源,例如图片和 SVG 图标。浏览器在解析 JavaScript 时花的时间要多得多。所以优化 JavaScript 也就变得非常重要。

# 减少 JavaScript 的网络传输开销

# Only sending the code a user needs.

一方面,只加载当前页面需要的 JavaScript 文件,可以使用 webpack 的code-splitting (opens new window)来解决。另一方面,懒加载一些不是必须的 JavaScript 文件。

# Minification

使用terser (opens new window)来压缩 JavaScript 代码。

# Compression

服务器开启 GZIP 来减少传输的文件大小。

# Removing unused code.

针对一些第三方 JavaScript 库,可以使用Tree Shaking (opens new window)来移除不需要的代码。

# Caching code to minimize network trips.

使用 ETag (opens new window), Last-Modified (opens new window), Cache-Control (opens new window) 三个配合有效的缓存 JavaScript 文件。

# 优化 JavaScript 下载和执行

我们可以通过使用 async 或者 defer 来优化 JavaScript 的下载和执行,两个关键字的具体作用看下图:

js async defer

# 总结

JavaScript 的优化并没有银弹,要根据具体项目的实际情况来处理。

# 参考

HTTP caching (opens new window)

JavaScript Start-up Optimization (opens new window)

Loading Third-Party JavaScript (opens new window)

前端开发中的加载性能优化

不同于需要安装的安卓 App 或者 iOS App,前端 App 所有的资源文件都要通过网络进行下载,所以加载速度越快对用户的体验来说就越好。因为我们也需要在加载的时候进行优化,减少不必要的资源请求。

# 文本内容的优化

# 压缩代码

HTML,JS,CSS 都有相应的工具可以进行代码压缩,可以使用 webpack 工具方便的进行代码压缩。JS 使用工具terser (opens new window),CSS 使用CSS Nano (opens new window), HTML 使用HTMLMinifier (opens new window)进行代码压缩。

# 使用 GZIP 进行压缩

现代化浏览器都支持 GZIP 进行压缩,并且服务器端 NGINX 也可以很方便的配置使用 GZIP 压缩请求的资源文件。

# 减少第三方 JS 的引用

在 2010 年左右,人们都爱使用 jQuery 框架进行开发,因为 jQuery 抹平了浏览器之间的差异性,大大提高了开发效率。但随着浏览器吸收了 jQuery 的各种优点,例如可以使用document.querySelector很方便的像 jQuery 一样选择元素。现在的前端开发已经不那么需要 jQuery 了,你可以访问You might not need jQuery (opens new window)来查找替代的方法。

# webpack 相关的优化

可以使用 webpack 的SplitChunksPlugin (opens new window), 分割 JS 文件,只打包首次载入需要的 JS 文件来减少网络请求。 我们也可以使用Tree Shaking (opens new window)来引入需要的 JS 库,避免不使用的代码被打包进来。

# 图像内容的优化

# 移除不使用的图像

由于网站项目的更新,很多时候有一些不被使用的图像资源被打包进输出目录。这样会导致无谓的资源加载,需要及时发现和删除。

# 选择合适的图像格式

众所周知,png 图像可以展示透明效果,但是 jpg 图像做不到。但是因为 png 比 jpg 多了一个 alpha 通道,所以占用的空间也大,如果不需要透明效果展示,相同的图像效果,jpg 会占用更小的空间。

# 移除图像的 Metadata

图像的 Metadata 对于 web 资源来说并没有什么意义,所以移除 Metadata 可以减少图像占用空间。

# 调整图像尺寸

如果显示的尺寸和实际尺寸差距过大,也会造成不必要的资源浪费。

# 调整图像质量

在很多情况下,对图像质量没有过高的要求,可以损失质量来换取更小的空间。

# 压缩图像

现在有很多算法可以有损或者无损的压缩图像,在发布之前,可以使用压缩工具减少图像的使用空间。

# HTTP 请求优化

可以使用 HTTP2 协议来提高网站的载入速度,HTTP2 允许多路复用,多个请求可以使用单一的 HTTP 连接来处理,大大提高了载入速度。 这里有一个demo (opens new window) 大家可以使用浏览器打开,感受一下。

# HTTP Cache

可以通过缓存技术来提高网站的载入速度,当用户再次访问网站的时候可以直接使用缓存而不必再次请求资源文件。我们甚至可以使用Service Workers (opens new window)缓存整个网站,保证可以离线使用。

# 总结

载入优化需要从各个方面入手,查找分析前端 App 的资源文件,并从网络请求和缓存下手才能达到最优的效果。

# 参考

Loading Performance (opens new window)

JavaScript开发中的性能优化

最近工作比较清闲,5 月又换了一个工作环境。总结下最近看的有关 JavaScript 性能的知识,并记下来供未来的自己参考。希望自己能不忘初心,继续成长!

# 使用 requestAnimationFrame 来更新动画

使用requestAnimationFrame把动画渲染交给浏览器,可以保证渲染保持在 60FPS。应该避免使用setTimeout或者setInterval来实现动画,因为计时器和事件队列会消耗更多的资源,还会导致无用的页面重新绘制。

# 使用 Web Workers 来进行复杂的运算

可以把单纯的计算放在 Web Workers 中,这样不影响主页面的渲染和流畅,例如加密和矩阵变换的运算就可以完全放在 Web Workers 中来减少主线程的执行时间,避免浏览器渲染堵塞。

# 避免微优化 JavaScript

举个最简单的例子,我曾经在一本书上看到过一个提升程序效率的例子。大致是这样的:

var array = [1, 2, 3, ...100];

for (var i = 0; i < array.length; i++) {
  console.log(array[i]);
}
1
2
3
4
5

这里的array.length获取数组的长度,每次都要计算数组长度会消耗不少时间,优化之后的代码是这样的:

var array = [1, 2, 3, ...100];
var len = array.length;
for (var i = 0; i < len; i++) {
  console.log(array[i]);
}
1
2
3
4
5

通过缓存数组的长度来保证只计算一次。这就是典型的微优化,说实话这段代码我一直在用,直到最近读了其他的书才发现,现在的 JS 解释器早就优化了对数组长度的计算。无论是读取一次还是一万次消耗的时间都没有太大差别。微优化应该是 JS 引擎需要做的事情,我们不应该在实际开发中在这方面耗费过多的时间。

# 滑动事件优化

当用户监听滑动事件并执行相关动画操作的时候,记得使用window.requestAnimationFrame来优化动画的执行。

function onScroll(evt) {
  // Prevent multiple rAF callbacks.
  if (scheduledAnimationFrame) return;

  scheduledAnimationFrame = true;
  requestAnimationFrame(readAndUpdatePage);
}

function readAndUpdatePage() {
  // do something
  requestAnimationFrame(readAndUpdatePage);
}

window.addEventListener('scroll', onScroll);
1
2
3
4
5
6
7
8
9
10
11
12
13
14

参考:

Debounce Your Input Handlers (opens new window)

Optimize JavaScript Execution (opens new window)