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)

vue实现datepicker组件

前端组件化的今天,选择日期组件算是最复杂的一个了吧。我们需要考虑日期显示的多语言,弹框的显示位置,以及日期月份的计算。

# 日期相关计算

计算每个月的天数,这个是不变的。一三五七八十腊,三十一天永不差;四六九冬三十整,惟有二月二十八,闰年还要把一日加。

function getDayCountOfMonth(year: number, month: number) {
  if (month === 3 || month === 5 || month === 8 || month === 10) {
    return 30;
  }

  if (month === 1) {
    if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
      return 29;
    } else {
      return 28;
    }
  }

  return 31;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

计算每个月的 1 号是周几:

function getFirstDayOfMonth(date: Date) {
  const temp = new Date(date.getTime());
  temp.setDate(1);
  return temp.getDay();
}
1
2
3
4
5

其他计算函数可以去看完整代码date.ts (opens new window)

# 弹窗定位相关

点击日期输入框,需要弹出下拉菜单,下拉菜单位置的计算并不简单,需要考虑到浏览器的窗口,如果输入框在下方,需要在上方弹出,如果输入框在上方,需要在下方弹出。 并且用户滑动到可视范围以外的话,还要可以隐藏。所以我们这里引用了一个比较成熟的第三方库来解决这个问题。 popperjs (opens new window) 这个库可以帮我们解决上面的问题,节约开发的成本。

# 多语言支持

日期选择组件,是为数不多需要做多语言支持的组件。因为我们要显示月份和每周的名字。就不得不做多语言处理了。目前我做的 demo 里面包含了三种语言的支持。

# 总结

日期选择组件,常见的需求有单日期选择和日期范围选择。优秀的组件需要同时满足这两个需求。并且尽量保证代码的简洁性。为此,我在 Github 写了一个 demo 库,希望可以给大家参考。

vue-datepicker (opens new window)