Published on

前端性能优化和可维护性实践

Authors
  1. 性能优化:网络请求 -> 资源加载 -> 代码与架构 -> 渲染性能 -> 感知体验
优化维度实践具体操作
​网络请求​1. 接口归一,减少请求
2. 服务端开启GZIP
3. CDN加速
4. HTTP2
5. HTTP缓存
1. 用户登录后,有一些系统默认配置项/用户默认配置项的查询,原本分散在各个页面/组件,后来把它们合并为一个接口,登录成功后直接将数据存储进 localStorage 进行共享(注意涉及鉴权类数据,不可直接存入,有安全隐患)
2. 服务端开启 GZIP 压缩
3. CDN 加速
4. 使用 HTTP2,实现多路复用,解决 http1.1 里 TCP 最大连接数的限制(6 个)
5. 配置更精准的 http 缓存策略,比如不常变化的静态资源( 页面品牌 logo,活动 banner 图),将其 Cache-Control:max-age=31536000(强缓存),而经常更新的资源配置为 Etag(协商缓存)
​资源加载​1. 组件按需引入
2. 代码压缩
3. 按需加载/Code Split
4. 资源压缩(图片/字体)
1. 部分组件只引入一部分(比如只用 antd 的部分组件)
2. 代码压缩:uglifyJsPlugin--只在正式环境开启,避免影响开发阶段效率
3. webpack提供的按需加载(umi 的按需加载,umi3.x dynamicImport: , umi4 的时候直接用原生的 lazy 导入组件),以及手动控制按需加载,Tree Shaking / Code Split
4:图片降级 avif -> webp -> png,设置默认的宽高,优化cls;字体降级(woff2 -> woff -> ttf)打包后的 dist 大小可降低 60% 左右);静态资源压缩(svg压缩,引入三方静态资源的时候,还要注意引入生产版本)
​代码与架构1. 轻量库替换(dayjs)
2. 去除不必要插件
3. JS/CSS编写优化
1. 三方依赖库替换:dayjs 替换 momentjs
2. 比如版本迭代过程中引入的三方库/webpack插件,后续废弃的
3. 代码层面:
3.1 避免频繁操作DOM(在一个循环中改DOM)
3.2 将长任务拆分为多个微任务(setTimeout/ requestIdleCallback),涉及复杂计算的,直接放 web worker 里面
3.3 尽量避免全局 window 上的事件监听:比如 resize,mousemove ,scroll 之类,实在需要时,也要做 防抖/节流 处理。用户可能频繁点击造成错误的地方,都要注意防抖处理
3.4 本地数据的缓存:利用 localStorage/SessionStorage,react 代码层面的,useMemo,useCallBack。通过es6单例实现数据的存储和消费。
3.5 注意 组件/事件/定时器 的正确销毁,避免内存泄露
3.6 如非业务必须,默认接口全部并行触发
​渲染性能​1. 懒加载
2. 虚拟滚动
3. 优化渲染逻辑
4. 开启GPU加速
5. DOM查询优化
6. 表格渲染优化
7. 超大流量页面
1. 多层级数据分层懒加载(主要是针对树,直接一把拉出来数据的话,接口等待时间过长)
2. 树/列表的虚拟滚动
3. 避免使用复杂的css样式计算,比如 hover 的时候设置 box-shadow/marginLeft 造成重排重绘问题
4. GPU 加速:可以仅限定transform触发合成层更新(transform,opacity,filter,will-change)
5. 慎用 querySelectorAll,使用精准的css选择器,减少嵌套(浏览器是从右向左解析的)
6. 表格 hover 高亮,从 js 实现改为 css 实现;数据分页;区分渲染优先级:纯数据列,操作列,鼠标移入后再渲染 tooltip, confirm 组件;利用 shouldCellUpdate 方法,当数据真正变化时才重新渲染;复杂的数据格式化也要避免在前端处理,或者放入 web worker 单独搞
7. 超大流量页面,比如发布会当天,用户使用的活动发布页。直接采用静态页面展示的方法,不建立编辑器的协同,只关注核心功能点可用
​感知体验​1. Loading(全局/图片)/骨架屏
2. 始终有兜底的错误提示信息,引导用户操作
1. 注意占位图的宽高
2. 注意提供切实可操作的提示信息
  1. 可维护性:
  • 适时的代码重构,进一步抽象业务,向组件化,模块化发展
  • 归档 sourceMap 用于线上问题的定位
  • 通过日志打点和接入监控系统,及时发现错误和感知待优化内容