前端性能优化

2023-09-01 浏览器性能优化

最近在开发了一个后台,项目打包部署后,发现首屏加载速度巨慢,出现长时间的白屏。今天记录一下我优化的思路和方法

  • 路由懒加载、组件懒加载

# 1、路由懒加载

SPA 项目,一个路由对应一个页面,如果不做处理,项目打包后,会把所有页面打包成一个文件, 当用户打开首页时,会一次性加载所有的资源 ,造成首页加载很慢,降低用户体验

列一个实际项目的打包详情:

  • app.js 初始体积:1175 KB

img

  • app.css 初始体积:274 KB

img

将路由全部改成懒加载

// 通过webpackChunkName设置分割后代码块的名字
const Home = () => import( /* webpackChunkName: "home" */ "@/views/home/index.vue");
const MetricGroup = () => import( /* webpackChunkName: "metricGroup" */ "@/views/metricGroup/index.vue");…………
const routes = [{
        path: "/",
        name: "home",
        component: Home
    },
    {
        path: "/metricGroup",
        name: "metricGroup",
        component: MetricGroup
    }, …………
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14

重新打包后,首页资源拆分为 app.js 和 home.js,以及对应的 css 文件

  • app.js:244 KB 、 home.js:35 KB

img

  • app.css:67 KB 、 home.css:15 KB

img

通过路由懒加载,该项目的首页资源压缩约 52%

# 路由懒加载原理

懒加载前提的实现:ES6 的动态地加载模块——import()

调用 import() 之处,被作为分离的模块起点,意思是,被请求的模块和它引用的所有子模块,会分离到一个单独的 chunk

要实现懒加载,就得先将进行懒加载的子模块分离出来,打包成一个单独的文件

webpackChunkName 作用是 webpack 在打包的时候,对异步引入的库代码(lodash)进行代码分割时,设置代码块的名字。webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中

# 2、组件懒加载

除了路由的懒加载外,组件的懒加载在很多场景下也有重要的作用

举个 🌰:

home 页面 和 about 页面,都引入了 dialogInfo 弹框组件,该弹框不是一进入页面就加载,而是需要用户手动触发后才展示出来

home 页面示例:

<template>
  <div class="homeView">

    <p>home 页面</p>
    <el-button @click="dialogVisible = !dialogVisible">打开弹框</el-button>
    <dialogInfo v-if="dialogVisible" />

  </div>
</template>
<script>
import dialogInfo from '@/components/dialogInfo';
export default {
  name: 'homeView',
  components: {

    dialogInfo

  }
}
</script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

项目打包后,发现 home.js 和 about.js 均包括了该弹框组件的代码(在 dist 文件中搜索 dialogInfo 弹框组件)

img

当用户打开 home 页时,会一次性加载该页面所有的资源,我们期望的是用户触发按钮后,再加载该弹框组件的资源

这种场景下,就很适合用懒加载的方式引入 弹框组件懒加载:

<script>
const dialogInfo = () => import(/* webpackChunkName: "dialogInfo" */ '@/components/dialogInfo');
export default {
  name: 'homeView',
  components: {
    dialogInfo
  }
}
</script>
1
2
3
4
5
6
7
8
9

重新打包后,home.js 和 about.js 中没有了弹框组件的代码,该组件被独立打包成 dialogInfo.js,当用户点击按钮时,才会去加载 dialogInfo.js 和 dialogInfo.css

img

最终,使用组件路由懒后,该项目的首页资源进一步减少约 11 %

# 组件懒加载的使用场景

有时资源拆分的过细也不好,可能会造成浏览器 http 请求的增多 总结出三种适合组件懒加载的场景:

  • 该页面的 JS 文件体积大,导致页面打开慢,可以通过组件懒加载进行资源拆分,利用浏览器并行下载资源,提升下载速度(比如首页)
  • 该组件不是一进入页面就展示,需要一定条件下才触发(比如弹框组件)
  • 该组件复用性高,很多页面都有引入,利用组件懒加载抽离出该组件,一方面可以很好利用缓存,同时也可以减少页面的 JS 文件大小(比如表格组件、图形组件等)

# 实践意义

  • 通过路由懒加载,只有在用户访问特定路由时才加载对应的组件,大大减少了初始加载的资源量,从而提高首屏加载速度。
  • 快速的首屏加载速度可以让用户更快地看到应用的主要内容,提高用户满意度, 减少等待时间,提供更流畅的用户体验。
  • 一次性加载所有组件可能会占用大量内存,避免不必要的内存占用,提高应用的稳定性和性能。。
  • 组件懒加载可以根据应用的具体需求动态加载组件,实现真正的按需加载。这对于一些特定场景下才会使用的组件非常有用,可以避免不必要的资源浪费。

# 总结

Vue 路由懒加载和组件懒加载是提高应用性能、优化用户体验的重要技术手段。通过按需加载路由和组件,可以减少初始加载的资源量,提高首屏加载速度,减少内存占用,同时也便于代码的维护和扩展。在实际开发中,应根据应用的具体需求合理使用这两种技术,以提高应用的整体性能和用户体验。

更新时间: 2024/9/27 下午6:33:04
大鱼-钢琴版
赵海洋