第175题 前端性能优化

前言

  • 是一个综合性问题,没有标准答案,但要求尽量全面
  • 某些细节可能会问:防抖、节流等

性能优化原则

  • 多使用内存、缓存或其他方法
  • 减少CPU计算量,减少网络加载耗时

从何入手

  • 让加载更快
    • 减少资源体积:压缩代码
    • 减少访问次数:合并代码,SSR服务端渲染,缓存
      • SSR
        • 服务端渲染:将网页和数据一起加载,一起渲染
        • SSR模式(前后端分离):先加载网页,在加载数据,在渲染数据
      • 缓存
        • 静态资源加hash后缀,根据文件内容计算hash
        • 文件内容不变,则hash不变,则url不变
        • url和文件不变,则会自动触发http缓存机制,返回304
    • 减少请求时间:DNS预解析,CDNHTTP2
      • DNS预解析
        • DNS解析:将域名解析为IP地址
        • DNS预解析:提前解析域名,将域名解析为IP地址
        • DNS预解析的方式:<link rel="dns-prefetch" href="//www.baidu.com">
      • CDN
        • CDN:内容分发网络,将资源分发到离用户最近的服务器上
        • CDN的优点:加快资源加载速度,减少服务器压力
        • CDN的缺点:增加了网络延迟,增加了服务器成本
      • HTTP2
        • HTTP2HTTP协议的下一代版本
        • HTTP2的优点:多路复用,二进制分帧,头部压缩,服务器推送
  • 让渲染更快
    • CSS放在headJS放在body下面
    • 尽早开始执行JS,用DOMContentLoaded触发
        window.addEventListener('load',function() {
      // 页面的全部资源加载完才会执行,包括图片、视频等
    })
    window.addEventListener('DOMContentLoaded',function() {
      // DOM渲染完才执行,此时图片、视频等可能还没有加载完
    })
* 懒加载(图片懒加载,上滑加载更多) ![](/images/s_poetries_work_uploads_2023_02_8f0de9086d90c75c.png)
* 对`DOM`查询进行缓存 ![](/images/s_poetries_work_uploads_2023_02_93d7e1f458b5b1a1.png)
* 频繁`DOM`操作,合并到一起插入到`DOM`结构 ![](/images/s_poetries_work_uploads_2023_02_5b7fc06e1aef4c9f.png)
* 节流、防抖,让渲染更流畅 
  * **防抖**
    * 防抖动是将多次执行变为`最后一次执行`
    * 适用于:`input`、`click`等
                        const input = document.getElementById('input')
            // 防抖
            function debounce(fn, delay = 500) {
              // timer 是闭包中的
              let timer = null
              // 这里返回的函数是每次用户实际调用的防抖函数
              // 如果已经设定过定时器了就清空上一次的定时器
              // 开始一个新的定时器,延迟执行用户传入的方法
              return function () {
                if (timer) {
                  clearTimeout(timer)
                }
                timer = setTimeout(() => {
                  fn.apply(this, arguments)
                  timer = null
                }, delay)
              }
            }
            input.addEventListener('keyup', debounce(function (e) {
              console.log(e.target)
              console.log(input.value)
            }, 600))
  * **节流**
    * 节流是将多次执行变成`每隔一段时间执行`
    * 适用于:`resize`、`scroll`、`mousemove`等
                        const div = document.getElementById('div')
            // 节流
            function throttle(fn, delay = 100) {
              let timer = null
            
              return function () {
                if (timer) { // 当前有任务了,直接返回
                  return
                }
                timer = setTimeout(() => {
                  fn.apply(this, arguments)
                  timer = null
                }, delay)
              }
            }
            // 拖拽
            div.addEventListener('drag', throttle(function (e) {
                console.log(e.offsetX, e.offsetY)
            }))
Last Updated:
Contributors: leeguooooo