- Published on
前端性能优化和可维护性实践
- Authors
- Name
- Li WenKang
- https://x.com/liwenkang_space
- 性能优化:网络请求 -> 资源加载 -> 代码与架构 -> 渲染性能 -> 感知体验
优化维度 | 实践 | 具体操作 |
---|---|---|
网络请求 | 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. 注意提供切实可操作的提示信息 |
- 可维护性:
- 适时的代码重构,进一步抽象业务,向组件化,模块化发展
- 归档 sourceMap 用于线上问题的定位
- 通过日志打点和接入监控系统,及时发现错误和感知待优化内容