本文旨在整理常见的Web前端性能优化思路,可以作为前端开发的参考。限于篇幅和篇幅,具体的实现方案不再详述。基于现代web前端框架的应用,其原理是通过浏览器向服务器发送网络请求,获取必要的index.html并打包JS、CSS等资源,在浏览器中执行JS,动态获取数据并渲染页面,将结果呈现给用户。在这个过程中,有两个步骤可能比较耗时,一个是网络资源的加载,另一个是浏览器中的代码执行和DOM渲染。耗时增加会导致页面响应变慢、卡顿,影响用户体验。针对以上两种耗时情况,常见的优化方向包括:缩短请求耗时;减少重排和重绘;提高JS性能。1.缩短请求耗时网络资源是Web应用的基础,提高网络资源的加载速度将显着提升前端性能。1、优化打包资源的总原则:减少或延迟模块引用,以减少网络负载。常用工具:webpackwebpack-bundle-analyzer可视化分析工具常用方法:缩减体积:减少不必要的导入;压缩JS代码;配置服务器gzip等;使用WebP图片;按需加载:根据“路由”、“可见”按需加载JS代码,减少第一次加载JS的体积。例如import()可以用于代码切分和按需加载;分离打包:利用浏览器缓存机制,根据模块更新频率分层打包。其他方式:Sprite图片:每个HTTP/1.1请求都是一个独立的TCP连接,最多6个并发连接,合并图片资源可以优化加载速度。HTTP/2不再需要这样做。2、CDN加速的总体原理:通过分布式边缘网络节点,缩短资源到终端用户的访问时延。常用工具:CloudflareAWSCloudFrontAliyunCDN常用方法:图片、视频等大容量文件加速3、浏览器缓存的一般原则:避免重复传输相同数据,节省网络带宽,加速资源获取。常用方法:可以通过设置HTTPHeader来控制缓存策略,一般如下。强缓存:Expires:HTTP/1.0Cache-Control:HTTP/1.1协商缓存:ETag+If-None-MatchLast-Modified+If-Modified-Since以ETag为例,如果给定的If-None-Match值浏览器与服务一致,如果客户端给的ETag值相等,服务端会直接返回304,从而避免数据重复传输。ETag示例:如果多个配置同时存在,则优先级为:Cache-Control>Expires>ETag>Last-Modified。4、高版本HTTP的一般原则:使用高版本HTTP来提高性能。常用工具:HTTP/2HTTP/2相对于HTTP/1.1最大的改进是:多路复用:单个TCP连接,多个HTTP请求;标头压缩:减少HTTP标头体积;请求优先级:优先获取重要数据;服务端推送:主动推送CSS等静态资源。其他方式:HTTP/3HTTP/3基于UDP,有很多性能提升,比如多路复用不阻塞队列头,响应速度更快。有兴趣的同学可以参考Wiki。5、WebSocket的总体原理:解决HTTP协议无法实时通信的问题。WebSocket是一种有状态的TCP长连接,用于实时通信和实时响应。6、服务端渲染(SSR)的一般原理:第一次访问时,服务端直接返回渲染后的页面。大致过程:浏览器向URL发送请求;服务器返回“空白”index.html;浏览器无法渲染页面,需要继续下载依赖;只有在加载所有脚本后才能呈现该组件。SSR过程:浏览器向URL发送请求;服务端执行JS完成首屏渲染返回;浏览器直接渲染页面,然后继续下载其他依赖;加载完所有脚本后,该组件将再次呈现在客户端上。它将合并现有的视图。常用工具:Node.js,用于服务端执行代码,输出HTML到浏览器,支持所有主流前端框架Next.js,使用gatsby,服务端渲染React的框架,该工具用React生成静态网站不仅可以提升页面的用户体验,还可以应用于SEO。2.减少重排和重绘除了网络资源,影响前端性能的另一个因素是前端页面的渲染效率。虽然不同的前端框架之间存在一些差异,但是整体的优化思路是一致的。这里将以React为例。1、减少渲染量的总原则:不渲染不显示的部分。常用工具:react-windowreact-loadableJS原生,如IntersectionObserver框架,如React.lazy、react-intersection-observer常用方法:虚列表:只渲染可见区域;延迟加载:无限滚动;按需加载:页面只在切换过去时加载。下面以虚拟列表为例,使用react-window库只渲染可见区域的数据:2.减少渲染次数。总体思路:避免重复渲染。常用工具:lodashJS或框架自带常用方法:防抖、节流;对于React函数组件,合理使用副作用,拆分不相关的副作用;对于React类组件,可以使用shouldComponentUpdate或PureComponent来优化Rendering;使用缓存,例如React.memo;使用requestAnimationFrame而不是setInterval来执行动画。3、提升JS性能由于浏览器是单线程异步模型,长时间的计算会阻塞渲染进程,因此提升复杂计算有助于提升前端的整体性能。1、缓存复杂计算的总体思路:避免重复计算。常用方法:对于React函数组件,可以使用useMemo来缓存复杂的计算值。比如memoizedValue需要通过复杂的计算得到。这时可以使用useMemo缓存,只有当输入参数发生变化时才重新计算,避免计算阻塞页面渲染,从而避免页面卡顿。constMyFunctionalComponent=()=>{constmemoizedValue=useMemo(()=>{computeExpensiveValue(a,b);},[a,b]);return
