工程化体系专栏永远首发自我的 Github,大家可以关注点赞,通常会早于发布各大平台一周时间以上。
本文涉及到的源码及视频地址:
前言
经常有读者问我什么是前端工程化?该怎么开始做前端工程化?
聊下来以后得出一些结论:这类读者普遍就职于中小型公司,前端人员个位数,平时疲于开发,团队内部几乎没有基础建设,工具很蛮荒。工程化对于这些读者来说很陌生,基本不知道这到底是什么,或者说认为 Webpack 就是前端工程化的全部了。
笔者目前就职于某厂的基础架构组,为百来号前端提供基础服务建设,对于这个领域有些许皮毛经验。因此有了一些想法,前端搞工程化会是笔者今年开坑的一个系列作品,每块内容会以文章 + 源码 + 视频的方式呈现。
这个系列的产出适用于以下群体:
-
中小厂前端,基建蛮荒,平时疲于业务,不知道业务外怎么做东西能提高自己的竞争力、丰富简历
-
公司暂时没有做基建计划,只能业余做一些低成本收益高的产品
-
想了解前端工程化
需要说明的是产出只会是一个低成本下的最小可用产品,你可以拿来按需增加功能、参考思路或者纯粹当学习一点知识。
什么是前端工程化?
因为是该系列第一篇文章,就先来大致说下什么是前端工程化。
我的理解是前端工程化大体上可以理解为是做提效工程,从写代码开始的每一步都可以做工程化。比如说你用 IDE 对比记事本写代码的体验及效率肯定是不一样的;比如说 Webpack 等这类工具也是在帮助我们提升开发、构建的效率,其他的工具也就不一一列出了,大家知道意思就好。
当然了,今天要聊到的性能检测也是工程化的一部分。毕竟我们需要有个工具去协助找到应用到底在哪块地方存在性能短板,能帮助开发者更快地定位问题,而不是在生产环境中让用户抱怨产品卡顿。
为什么需要性能检测?
性能优化是很多前端都绕不开的话题,先不说项目是否需要性能优化,面试的时候这类问题是很常见的。
但是光会性能优化的手段还是不够的,我们最后还是需要做出前后数据对比才能体现出这次优化的价值到底有多少,毕竟数据的量化在职场中还是相当重要的。老板不知道你具体做的事情,很多东西都得从数据中来看,数据越好看就说明你完成工作的能力越高。
想获取性能的前后数据变化,我们肯定得用一些工具来做性能检测。
性能该怎么检测?
性能检测的方式有很多:
-
Chrome 自带的开发者工具:Performance
-
Lighthouse 开源工具
-
原生 Performance API
-
各种官方库、插件
这些方法各有各的好处,前两种方式简单快捷,能够可视化各类指标,但是很难拿到用户端的数据,毕竟你不大可能让用户去跑这些工具,当然除此之外还有一些很小的缺点,比如说拿不到重定向次数等等。
官方库、插件相比前两者来说会逊色很多,并且只提供一部分核心指标。
原生 Performance API 存在兼容问题,但是能覆盖到开发生产阶段,并且功能也能覆盖自带的开发者工具:Performance 工具。不仅在开发阶段能了解到项目的性能指标,还能获取用户端的数据,帮助我们更好地制定优化方案。另外能获取的指标也很齐全,因此是此次我们产品的选择。
当然了这不是多选一的选择题,我们在开发阶段还是需要将 Performance 工具及 API 结合起来使用,毕竟他们还是有着相辅相成的作用。
实战
这是此处产品的源码:地址。
一些性能指标
在开始实战前,我们还是得来了解一些性能指标,随着时代发展,其实一些老的性能优化文章已经有点过时了。谷歌一直在更新性能优化这块的指标,笔者之前写过一篇文章来讲述当下的最新性能指标有哪些,有兴趣的读者可以先详细的读一下。
当然如果你嫌太长不看,可以先通过以下思维导图简单了解一下:
当然除了这个指标以外,我们还需要获取网络、文件传输、DOM等信息丰富指标内容。
Performance 使用
Performance
接口可以获取到当前页面中与性能相关的信息,并且提供高精度的时间戳,秒杀 Date.now()
。首先我们来看下这个 API 的兼容性:
这个百分比其实已经算是兼容度很高了,主流浏览器的版本都能很好的支持。
对于 Performance 上 API 具体的讲解文中就不赘述了,有兴趣的可以阅读 MDN 文档,笔者在这里只讲几个后续用到的重要 API。
getEntriesByType
这个 API 可以让我们通过传入 type
获取一些相应的信息:
- frame:事件循环中帧的时间数据。
- resource:加载应用程序资源的详细网络计时数据
- mark:
performance.mark
调用信息 - measure:
performance.measure
调用信息 - longtask:长任务(执行时间大于 50ms)信息。这个类型已被废弃(文档未标注,但是在 Chrome 中使用会显示已废弃),我们可以通过别的方式来拿
- navigation:浏览器文档事件的指标的方法和属性
- paint:获取 FP 和 FCP 指标
最后两个 type
是性能检测中获取指标的关键类型。当然你如果还想分析加载资源相关的信息的话,那可以多加上 resource
类型。
PerformanceObserver
PerformanceObserver
也是用来获取一些性能指标的 API,用法如下:
const perfObserver = new PerformanceObserver((entryList) => {
// 信息处理
})
// 传入需要的 type
perfObserver.observe({
type: 'longtask', buffered: true })
结合 getEntriesByType
以及 PerformanceObserver
,我们就能获取到所有需要的指标了。
上代码!
因为已经贴了源码地址,笔者就不贴大段代码上来了,会把主要的从零到一过程梳理一遍。
首先我们肯定要设计好用户如何调用 SDK(代指性能检测库)?需要传递哪些参数?如何获取及上报性能指标?
一般来说调用 SDK 多是构建一个实例,所以这次我们选择 class
的方式来写。参数的话暂定传入一个 tracker
函数获取各类指标以及 log
变量决定是否打印指标信息,签名如下:
export interface IPerProps {
tracker?: (type: IPerDataType, data: any, allData: any) => void
log?: boolean
}
export type IPerDataType =
| 'navigationTime'
| 'networkInfo'
| 'paintTime'
| 'lcp'
| 'cls'
| 'fid'
| 'tbt'
接下来我们写 class
内部的代码,首先在前文中我们知道了 Performance API 是存在兼容问题的,所以我们需要在调用 Performance 之前判断一下浏览器是否支持:
export default class Per {
constructor(args: IPerProps) {
// 存储参数
config.tracker = args.tracker
if (typeof args.log === 'boolean') config.log = args.log
// 判断是否兼容
if (!isSupportPerformance) {
log(`This browser doesn't support Performance API`)