前端体验优化地最终目的就是让用户的使用体感舒适,无阻塞、流畅的得到预期想要的结果,而其中的用户可分为三层:产品用户、公司同事和研发自己。UX、性能优化其实都是体验优化的子集,前端体验犹如下图的冰山那样,在水下别有洞天。
:-: ![](https://img.kancloud.cn/20/7f/207fdf1fae76a0b16fd639ee845bb8eb_2200x1400.jpeg =800x)
  可以将体验优化大致分为 5 个模块,分别是终端、网络、前端、后端以及数据,这 5 个模块可以形成一个闭环。
  终端就是浏览器、微信等一类设备,网络就是缓存、协议等一类概念,前端和后端针对的就是技术细节,而数据其实就是最后的分析,对优化前后进行量化对比,最终得出结论,判断此次优化是否成功。
  与以往的视觉体验优化(例如线框图的不同布局)不同,本文着重分析的前端体验侧重于技术端和数据分析,更偏向于前端开发人员,而不是 UI 设计人员。
:-: ![](https://img.kancloud.cn/b6/cb/b6cb1a206f73a5ea59ed8ac27335eb59_2000x1377.png =800x)
  下面是一张前端体验优化的[思维导图](https://github.com/pwstrick/daily/blob/master/assets/xmind/ux.xmind),还在持续更新中。
:-: ![](https://img.kancloud.cn/f8/0e/f80efe612f8563d1bf5ed81beaab4032_3436x11052.png =800x)
  其中终端模块的[图像](https://www.kancloud.cn/pwstrick/fe-questions/3131237)、[呈现](https://www.kancloud.cn/pwstrick/fe-questions/3133382),[网络模块](https://www.kancloud.cn/pwstrick/fe-questions/3139900),前端模块的[JavaScript](https://www.kancloud.cn/pwstrick/fe-questions/3136694)、[构建](https://www.kancloud.cn/pwstrick/fe-questions/3146571)都被记录在[前端性能精进](https://www.kancloud.cn/pwstrick/fe-questions/3126322)专栏中。
  数据模块的性能指标记录在方法论之[测量](https://www.kancloud.cn/pwstrick/fe-questions/3126323)和[分析](https://www.kancloud.cn/pwstrick/fe-questions/3128806),监控体系记录在[监控系统](https://www.kancloud.cn/pwstrick/fe-questions/2363166)专栏内(包括[SDK](https://www.kancloud.cn/pwstrick/fe-questions/2305450)、[存储和分析](https://www.kancloud.cn/pwstrick/fe-questions/2305451)、[页面奔溃](https://www.kancloud.cn/pwstrick/fe-questions/2363168))。
  终端优化的核心是减少渲染时间,网络优化的核心是减少延迟时间,另外三个模块都在服务于这两个模块。
  下图描绘了网页在加载过程中,各阶段与上述模块之间的优化关系。
:-: ![](https://img.kancloud.cn/3d/0b/3d0bc30add4428901063d1400059e772_3398x1342.png =800x)
## 一、终端
  终端最常用的就是浏览器,浏览器最需要关注的优化点是两个:图像和呈现。
1. 在网页中充斥着图像,而图像往往会增加网页的尺寸,所以优化的重点是用尽手段减小尺寸,例如动态裁剪、响应式、WebP、加载时机的转变等等。
2. 呈现涉及浏览器渲染和静态资源的请求,核心就是缩短渲染和资源加载时间,例如只渲染首屏、提前加载后续资源、对重要资源优先请求等等。
  微信是一款国民级APP,提供了 JSSDK 和小程序的功能,JSSDK 赋予了用户部分微信的能力,依托微信的生态,小程序现在有了非常广泛的应用。所以对于这个环境,也会有各类独特的优化手段,不过我本人还不熟悉这块。
  还有一个很重要的终端就是各类 APP 内置的 WebView,客户端通过 WebView 可以暴露出许多功能,帮助前端页面的优化,例如唤起客户端的登录和支付界面,还有就是最大限度的缓存网页资源,减少网络请求,例如容器化、离线包。
  除此之外,还可以增加预请求的能力,将串行的网络请求优化为并行的网络请求,充分利用空闲时间。
  诸如 Electron、WebRTC、多媒体等这类优化点,自己并不是很熟悉,在此也不再赘述。
## 二、网络
  当一个请求从终端发出到服务器接收,这段网络传输的时间,其实是我们不可控的。
  要优化就只能从起点和终点两处入手。最先想到的就是开启缓存:强缓存和协商缓存。
  日常使用最多的是协商缓存,但是在性能提升上,决定强缓存更为明显,因为强缓存后就不会再去服务器请求资源。
  不过,为了页面正确,还得设法破坏缓存,尤其是 HTML 文件,例如给 URL 包一层短链,在请求时自动加个时间戳,以此让缓存不再命中。
  HTTP 是一种网络协议,目前已经可以广泛使用 HTTP/2 协议,在之前的基础上做了许多优化,例如二进制分帧层、多路通信、首部压缩等,让数据传输的更快以及更大限度的利用好带宽。
  协议中的压缩字段,默认都已经开启,对于非媒体文件(例如 HTML、CSS、JavaScript 等)经过压缩后,尺寸可减少 50%,甚至 80%。
  HTTP/3 协议解决了上一个协议的几个问题,例如 TCP 队首阻塞、网络切换成本等,不过目前最大的问题还是支持度不够,不能大范围的使用。
  HTTPS 是 HTTP 的安全版本,目前有些浏览器默认会将 HTTP 的请求重定向到 HTTPS,这种多余的重定向完全可以避免。
  CDN 是一种网络加速服务,目前有很多公司都提供了这类服务,但就是要花钱,只要花钱了,海外都能给你加速,无论静态资源还是动态接口,都可以借助 CDN 加速,现在还能提供对图像的动态裁剪和压缩的功能。
  有时候浏览网页会遇到网关报出的 500、502、503、504 等错误,其实就是服务异常、找不到转发服务或转发服务在指定时间内未响应。
  对于未响应,可以从相关分析平台找出性能瓶颈,然后在后端部分进行代码优化,很多时候与数据库有关。无论如何,要尽一切可能避免此类错误,这类体验最为糟糕,无法得到预期结果。
## 三、前端
  前端现在已经离不开工程化构建,常见的 Webpack、Rollup 等打包工具提供了许多优化功能,例如压缩、合并、剪枝等,尽量减少网络请求和资源尺寸。
  除此之外,尽量减少和选择轻量级的依赖库,也能降低不少的尺寸。随着 IE 这个毒瘤退出舞台,移动端兴起之后,ES6 也被广泛的支持,很多时候都没必要降级到 ES5,再也不用平白无故的多出一大段代码了。
  ESBuild 也是一个构建工具,不过与之前的不同,它内部是用 go 编写的,所以说它非常快。
  Vite 的开发环境依赖的就是它,但是为了快,就没有提供 AST 的操作能力,导致目前很多的插件无法使用,所以 Vite 生产环境使用的还是 Rollup,是对性能与灵活性的一种平衡。
  前端三剑客之一的 JavaScript,是每个前端开发人员每日必会使用到的,对于它的优化基本上都是代码层面的优化,常见的节流和防抖,算法和数据结构,分解或异步执行长任务,本地存储等。
  有个库叫[Partytown.js](https://github.com/BuilderIO/partytown),比较有意思,可以将第三方脚本迁移到 Web Worker 中执行,防止阻塞主线程,不过这还只是个测试性的库。
  前端为了让自己的日常工作比较爽,技术栈不能太旧,否则很多新功能都体验不到,太可惜了。在升级技术栈时,还不能影响业务,运营、产品等人可不会在意你用什么技术栈,他们在意的是业务保持稳定,并且还能持续迭代。
  前端的基建包括组件化、标准化、工具化、自动化、文档化以及页面规范化,本质就是让自己组的开发效率能更高,与别人协作发生的错误能更少,产品上线后最好没有问题。一句话就是你要好,大家也要好,和谐办公。
  在功能上线前,可以对新功能加个开关,万一有问题,就直接关闭新功能,粒度可以是页面级别的。不过前端发版不像客户端那么困难,毕竟做开关是要成本的。灰度和 A/B 测试,在前端也可以执行。
## 四、后端
  传统的前端开发是不接触后端的,但是自从 Node.js 拓宽了前端的边界后,越来越多的前端开始涉足后端,那么就很有必要了解后端的体验优化。
  后端的优化大致可分为两部分:Node.js 和数据库,对于它们的监控,市面上有许多成熟的平台,自己搭建的话,成本有点高。
  我刚到公司时,还在用 Node.js 的 8.7 版本,明显太老,在挑选第三方库时,还得特地挑老版本,所以说,要将版本进行最适当的升级,在改造成本最小的前提下,升级到最高的那个版本。
  上一节讲到基建,其中很多内容都是需要借助 Node.js 实现的,例如通用配置、脚本执行等。
  还有下一节中的监控系统,也需要 Node.js 实现,并且还要涉及到消息队列、MySQL、ElasticSearch 等技术点。注意,对于那些非业务服务,需要单独分离,以免异常时影响线上业务。
  在有了后端能力后,就能自己写接口,接口的响应格式很重要,在统一后,更容易分析接口的成功和失败细节。并且对于接口,要有安全意识,以及不能因为接口的问题而让页面直接异常,需要用更友好的反馈方式。
  目前市面上有许多种数据库,常见的关系型数据库 MySQL,遇到比较多的问题就是数据量上去后的慢响应,很可能导致 504 异常,要么缩小查询范围,要么就是创建合适的索引。
  MySQL 处理百万级的数据量绰绰有余,但千万级就比较够呛了,此时除了索引加持外,还需要进行分表、数据归档等手段,其实本质都是为了减少数据量。
  与之前的 Node.js 服务类似,对于那些非业务表,可以单独生成一个库来存储,也是避免数据库异常导致线上业务出错。
  MySQL 全文检索的能力不行,所以对于大数据量的全文检索需要改用 ElasticSearch,还有那些需要联多张表的情况,也可以将数据存储到 ElasticSearch 中再做查询。
  Redis 其实也是一种非关系型的数据库,最大的特点就是快,若要对接口的查询进行优化, Redis 无疑是一种高效的手段。
  不过在用 Redis 时需要注意,它只是一种缓存,若没有它,也要能得到预期的数据。也就是说,尽量不要让业务逻辑依赖 Redis 中的数据,Redis 只是为了加速,即使没有了它,线上业务也不应该出错。
## 五、数据
  为了能更好的优化体验,很有必要量化性能,以及监控页面的方方面面。
  首先关于性能,目前已有很多工具,例如 Lighthouse、WebPageTest 和 Chrome Devtools,它们会分析页面的性能,不过这些只能算是实验室数据,并不是真实用户的数据。
  我们自研了性能监控系统,记录了一系列的指标,包括白屏、首屏等,在搜集过后,提供了多种图表进行性能分析。
  力图重现真实用户的使用场景,发现性能瓶颈。前端监控也是自研的,会记录页面的异常、通信、点击等行为,同样提供了各类图表。
  通过此系统,可以主动发现页面中的错误,而不是等待用户上报,并且还发现了许多冗余接口。
  除此之外,每天都会推送核心指标到前端的飞书群中,包括接口慢响应占比、SLA(服务质量保证,即5XX占比)等,关注服务的健康度。
  线上还会实时监控页面、接口和数据库的错误情况,当达到某一个阈值时,就会发送告警到飞书中,同样是为了在用户上报前发现问题。
  为了能更好的与公司同事协作,我们组制订的每双月的需求提测率和用户满意度评分,当然,这个用户是内部员工。
  之所以是提测率而不是完成率,是因为很多时候项目是要与服务端协作的,可能我们做完了,他们还没完成,而这种情况还比较普遍,所以就使用了提测率。
  除了技术监控之外,前端人员还需要了解业务监控数据,其实也是为了让自己能更好的理解业务,培养产品思维。
  通过埋点将某一处的动作,传输到服务器做存储,然后再经过数据分析人员,绘制成一张张的图表。埋点的采集并不复杂,常见的就是侵入式的在某一处位置加入埋点代码。
  若对页面做了某种优化,涉及到业务逻辑时,可以分析埋点数据,比对前后的变化,来决定优化是否成功。
  在我们公司,每一个小组都会有一个或两个北极星指标(例如用户新增数、XX营收、日志发布率等),指标的变化就是核心业务的变化。
  而在这个指标下面,还有许许多多的细节指标,支撑着北极星指标,以会员为例,日付费人数、日下单量、首次充值人数等。
  如果有条件的话,可以让分析人员开放些与自己有关的指标,再与相关人员紧密沟通,让这些数据更有活性。
*****
> 原文出处:
[博客园-前端体验优化](https://www.cnblogs.com/strick/category/2360021.html)
[知乎专栏-前端性能精进](https://www.zhihu.com/column/c_1610941255021780992)
已建立一个微信前端交流群,如要进群,请先加微信号freedom20180706或扫描下面的二维码,请求中需注明“看云加群”,在通过请求后就会把你拉进来。还搜集整理了一套[面试资料](https://github.com/pwstrick/daily),欢迎阅读。
![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200)
推荐一款前端监控脚本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不仅能监控前端的错误、通信、打印等行为,还能计算各类性能参数,包括 FMP、LCP、FP 等。
- ES6
- 1、let和const
- 2、扩展运算符和剩余参数
- 3、解构
- 4、模板字面量
- 5、对象字面量的扩展
- 6、Symbol
- 7、代码模块化
- 8、数字
- 9、字符串
- 10、正则表达式
- 11、对象
- 12、数组
- 13、类型化数组
- 14、函数
- 15、箭头函数和尾调用优化
- 16、Set
- 17、Map
- 18、迭代器
- 19、生成器
- 20、类
- 21、类的继承
- 22、Promise
- 23、Promise的静态方法和应用
- 24、代理和反射
- HTML
- 1、SVG
- 2、WebRTC基础实践
- 3、WebRTC视频通话
- 4、Web音视频基础
- CSS进阶
- 1、CSS基础拾遗
- 2、伪类和伪元素
- 3、CSS属性拾遗
- 4、浮动形状
- 5、渐变
- 6、滤镜
- 7、合成
- 8、裁剪和遮罩
- 9、网格布局
- 10、CSS方法论
- 11、管理后台响应式改造
- React
- 1、函数式编程
- 2、JSX
- 3、组件
- 4、生命周期
- 5、React和DOM
- 6、事件
- 7、表单
- 8、样式
- 9、组件通信
- 10、高阶组件
- 11、Redux基础
- 12、Redux中间件
- 13、React Router
- 14、测试框架
- 15、React Hooks
- 16、React源码分析
- 利器
- 1、npm
- 2、Babel
- 3、webpack基础
- 4、webpack进阶
- 5、Git
- 6、Fiddler
- 7、自制脚手架
- 8、VSCode插件研发
- 9、WebView中的页面调试方法
- Vue.js
- 1、数据绑定
- 2、指令
- 3、样式和表单
- 4、组件
- 5、组件通信
- 6、内容分发
- 7、渲染函数和JSX
- 8、Vue Router
- 9、Vuex
- TypeScript
- 1、数据类型
- 2、接口
- 3、类
- 4、泛型
- 5、类型兼容性
- 6、高级类型
- 7、命名空间
- 8、装饰器
- Node.js
- 1、Buffer、流和EventEmitter
- 2、文件系统和网络
- 3、命令行工具
- 4、自建前端监控系统
- 5、定时任务的调试
- 6、自制短链系统
- 7、定时任务的进化史
- 8、通用接口
- 9、微前端实践
- 10、接口日志查询
- 11、E2E测试
- 12、BFF
- 13、MySQL归档
- 14、压力测试
- 15、活动规则引擎
- 16、活动配置化
- 17、UmiJS版本升级
- 18、半吊子的可视化搭建系统
- 19、KOA源码分析(上)
- 20、KOA源码分析(下)
- 21、花10分钟入门Node.js
- 22、Node环境升级日志
- 23、Worker threads
- 24、低代码
- 25、Web自动化测试
- 26、接口拦截和页面回放实验
- 27、接口管理
- 28、Cypress自动化测试实践
- 29、基于Electron的开播助手
- Node.js精进
- 1、模块化
- 2、异步编程
- 3、流
- 4、事件触发器
- 5、HTTP
- 6、文件
- 7、日志
- 8、错误处理
- 9、性能监控(上)
- 10、性能监控(下)
- 11、Socket.IO
- 12、ElasticSearch
- 监控系统
- 1、SDK
- 2、存储和分析
- 3、性能监控
- 4、内存泄漏
- 5、小程序
- 6、较长的白屏时间
- 7、页面奔溃
- 8、shin-monitor源码分析
- 前端性能精进
- 1、优化方法论之测量
- 2、优化方法论之分析
- 3、浏览器之图像
- 4、浏览器之呈现
- 5、浏览器之JavaScript
- 6、网络
- 7、构建
- 前端体验优化
- 1、概述
- 2、基建
- 3、后端
- 4、数据
- 5、后台
- Web优化
- 1、CSS优化
- 2、JavaScript优化
- 3、图像和网络
- 4、用户体验和工具
- 5、网站优化
- 6、优化闭环实践
- 数据结构与算法
- 1、链表
- 2、栈、队列、散列表和位运算
- 3、二叉树
- 4、二分查找
- 5、回溯算法
- 6、贪心算法
- 7、分治算法
- 8、动态规划
- 程序员之路
- 大学
- 2011年
- 2012年
- 2013年
- 2014年
- 项目反思
- 前端基础学习分享
- 2015年
- 再一次项目反思
- 然并卵
- PC网站CSS分享
- 2016年
- 制造自己的榫卯
- PrimusUI
- 2017年
- 工匠精神
- 2018年
- 2019年
- 前端学习之路分享
- 2020年
- 2021年
- 2022年
- 2023年
- 日志
- 2020