前端性能优化

108 阅读2分钟

性能指标

性能的指标,浏览器的控制台中 网络(network) 和 性能(performance)。

image.png

network,请求次数越少,DOMContentLoaded(html 被完全解析和加载,不包含样式图片和框架的加载时间),load 越小,性能越好。

performance,fp 第一次看到白屏的时间。fcp 从开始加载到页面的任何一个内容在页面上渲染的时间。lcp 页面可视区域内最大的一块区域完全加载完的时间。

image.png

当然,以上分析比较复杂,我们可以使用一个插件 lighthouse 来评估性能。

image.png

优化方案

  • 数据懒加载处理方案
  • 图片懒加载处理方案
  • webpack 打包体积过大与CDN 优化处理方案
  • 其他优化方案(gzip、http 缓存、service worker)

数据懒加载

当需要展示的数据进入视口时,才向后端发送请求,IntersectionObserver - Web API | MDN (mozilla.org)

    <div class="box" ref="box3Target">
      <div class="title">{{ data03.title }}</div>
      <ul class="list">
        <li class="item" v-for="item in data03.list" :key="item.id">
          <img class="item-img" :src="item.img" alt="" />
          <div class="item-name">{{ item.name }}</div>
          <div class="item-desc">{{ item.desc }}</div>
        </li>
      </ul>
    </div>
onMounted(() => {
  const intersectionObserver = new IntersectionObserver((entries) => {
    // 当 intersectionRatio 为 0 时,目标在视野外
    if (entries[0].intersectionRatio <= 0) {
      return console.log('当前视图不可见')
    }
    console.log('当前视图可见')
  })
  // 开始监听
  intersectionObserver.observe(box3Target.value)
})

VueUse 里面已经对此进行了封装:useIntersectionObserver | VueUse

import { useIntersectionObserver } from '@vueuse/core'

const { stop } = useIntersectionObserver(
      // 注意,这里没有 .value
      box3Target,
      ([{ isIntersecting }]) => {
        if (isIntersecting) {
          console.log('视图可见')
          // 获取数据
          loadData03()
          // 触发 stop 监听停止
          stop()
        } else {
          console.log('视图不可见')
        }
      }
  )

图片懒加载

img 标签非常多,不可能通过把每个 img 标签的 dom 对象都获取到。所以我们可以使用 自定义指令。为需要懒加载的图片加上我们的自定义指令。

应用实例 API | Vue.js (vuejs.org)

directive/index.js

import { useIntersectionObserver } from '@vueuse/core'

const imgLazy = {
  mounted(el) {
    // console.log(el)
    // 图片懒加载:一开始不加载,等到将要看到时在加载
    // 1. 缓存当前的图片路径
    const catchSrc = el.src
    console.log(catchSrc)
    // 2. 把 img.src 变为占位图
    el.src = 'https://res.lgdsunday.club/img-load.png'
    // 3. 监听将要看到
    const { stop } = useIntersectionObserver(el, ([{ isIntersecting }]) => {
      if (isIntersecting) {
        // 4. 渲染图片
        el.src = catchSrc
        // 5. 停止监听
        stop()
      }
    })
  }
}

export default {
  // app.use 的方式使用
  install: (app) => {
    app.directive('imgLazy', imgLazy)
  }
}
<img v-imgLazy class="img" :src="item.path" alt="" srcset="" />

main.js

import directive from '@/directive'

app.use(directive)

打包优化

不论是使用 webpack 还是 vite ,打包后进行打包分析,针对于特别大的包,我们可以采用

  1. 排除依赖打包的方法使其在 build 时不打包
  2. 然后通过 cdn 引入所需的包。

但是要注意,cdn 只能增加用户访问的速度,但是不会减少依赖包的体积。

webpack 和 vite 都会有自己的 cdn 优化方案。

其他

  1. gzip 压缩

代码中重复度越高,可压缩的空间就越大。当Nginx返回js文件的时候,会判断是否开启gzip,然后压缩后再返回给浏览器。

该压缩方法需要Nginx配置开启Gzip压缩,单纯前端通过webpack插件开启Gzip压缩是不能达到优化效果的。

  1. http 缓存

一般来说,304 缓存的处理是服务框架中自动进行处理,不需要过多关注。

  1. service worker

对网站提供离线体验。使用并不广泛。