likes
comments
collection
share

前端单测学习(12)—— 性能优化

作者站长头像
站长
· 阅读数 29

前言

在往期的博客中,基本上已经对本人接触过各种类型的单测做了学习,今天就来讲一些性能相关的,在我们之前的项目中,我们写了一些单测,当然数量上还是比较少的,但是一旦我们的项目中的单测数量多起来的时候,我们每次运行全量的单测就会导致耗时越来越长,这个就变成我们需要去面对去解决的问题。今天就笔者接触过的一些优化方法做一些小结,还是在之前的项目中做一些改造,但是因为原先项目单测的数量不算特别多,这个优化不一定能够很明显,但是笔者在实际项目中实际上确实是有提效,这个看到的朋友可以自己去尝试一下。

Jest 架构

我们要解Jest的性能问题,首先就是要清楚Jest是是怎么运行的,找一下Jest作者的一些分享视频,可以扒拉到一个Jest的一个执行流程,我们可以根据这个流程找到几个影响性能的步骤,从这几个步骤我们可以找到几个可优化的点

前端单测学习(12)—— 性能优化

从上图可以看到,最影响 Jest 性能的有 3 个地方:

  • 使用 jest-haste-map 生成虚拟文件系统
  • 多线程执行测试任务
  • 转译 JavaScript 代码

虚拟文件系统

如果要在HMR的时候修改文件,jest-cli需要对项目中的文件做一次遍历,这明显是一个很损耗性能的点,特别是在文件特别多的项目中,如果是在本地电脑执行的话可能会导致风扇呼呼作响,卡得动不了。 虚拟文件系统就是来解决这个问题的,第一次启动的时候就遍历整个项目,把文件用Map的形式存储起来,监听到具体哪个文件发生了变更之后,只需要增量修改这个Map就可以。这个思路除了用于HMR场景,同理可用于--watch场景 我们在可以留一下在原先项目中跑单测

pnpm test

之后我们改了具体的.tsx文件之后运行的速度就快了,就是这个道理。当然,这个点我们是做不了什么优化的,只是做一个了解。

多线程

Jest可以利用Node.js的worker来开启多线程来跑用例,在大型项目中,如果是有几千个测试case的时候是有不少的提效的。但是线程不是越多越好,毕竟每个线程都是有额外的开始。默认情况下不做配置,Jest默认最大的Worker数是CPU数 - 1,1这线程是用于jest-cli,其他的用于跑测试case。没有配置maxWorkers的时候默认是用最多的Worker,当我们的测试case数量比较少的时候会比较慢,笔者的实际项目中是设置了2个。当然默认值在大部分情况下是能够满足了,是否需要设置还是得自己判断下。

我们尝试在原先的项目设置一下maxWorkers

"jest": {
    "maxWorker": 2,
    ...
}

照之前的运行一下看看

pnpm test

前端单测学习(12)—— 性能优化

居然报错了...看下报错,其实是说的CRA只支持更改指定的几个参数,其他的目前不支持,如果我们要覆盖其他几个参数的话需要其他的设置 我们新建一个jest.config.js,然后把原先在package.json中的jest配置迁移进去,然后加上我们的maxWorkers参数即可 改一下运行的脚本运行即可

"scripts": {
    "test": "react-scripts test -- --config jest.config.js",
}

这里注意一点,CRA还是会在控制台提醒报错,CRA建议还是用package.json中配置的形式,而且是指定几个参数,但是不会组织case的运行,由于笔者实际项目中不是用的CRA,这里就不展开叙述。

文件转译

Jest是在执行到具体的case文件的时候再做转译,我们知道,现在js的转译器有多种,比如tsc babel,当然还有后起之秀的swcesbuild,所以思路就是用其他的转译器来做转译,达到提速的效果

swc

我们这些是在本地的转译,所以我们增加两个包的依赖,如下

"devDependencies": {
    ...
    "@swc/jest": "~0.2.21",
    "@swc/core": "~1.2.197"
}

补充之后就是安装一下依赖pnpm i 我们修改一下配置,如果是jest.config.js的话可以用如下的配置

const swcJestConfig = {
  sourceMaps: true,

  jsc: {
    parser: {
      syntax: 'typescript',
      tsx: true,
    },

    transform: {
      react: {
        runtime: 'automatic',
      },
    },
  },
};

module.exports = {
  // 不用 ts-jest
  // preset: "ts-jest", 

  transform: {
    // 使用 swc 转译 JavaScript 和 TypeScrit
    "^.+\.(t|j)sx?$": ["@swc/jest", swcJestConfig],
    ...
  },
}

swcJestConfig这个可以根据实际情况调整,笔者在项目中是补充了一些其他的配置,不加这个config也是可行的,具体情况根据实际项目的情况做调整。

esbuild

同上面swc类似,我们还是安装一下对应的包

pnpm i esbuild esbuild-jest --save-dev

然后我们修改一下jest.config.js的配置,然后重新运行即可看到效果,同样还可以设置配置,在数组中可以在第二个位置增加配置

"transform": {
  "^.+\\.tsx?$": ["esbuild-jest"]
},

总结

本期主要是讲述了一些优化的方案,不过因为之前我们用来实验的这个项目单测数量比较有限,所以效果不一定很明显,另外就是CRA的限制,在工程上还是有些影响,本篇博客主要是讲解一些思路,实际的配置和效果需要根据实际项目做调整,这里不再赘述。

传送门

前端单测学习(1)—— 单测入门之react单测项目初步 前端单测学习(2)—— react 组件单测初步 前端单测学习(3)—— react组件单测进阶 前端单测学习(4)—— react 组件方法&fireEvent 前端单测学习(5)—— 快照 前端单测学习(6)—— 定时器 前端单测学习(7)—— mock 前端单测学习(8)—— react hook 前端单测学习(9)—— 覆盖率报告 前端单测学习(10)—— 状态管理redux 前端单测学习(11)—— react hook 进阶 前端单测学习(12)—— 性能优化 前端单测学习(13)—— 自动化测试

代码仓库:github.com/liyixun/rea…