前端性能优化方案

154 阅读3分钟

1. 首屏速度

首屏速度包括 白屏时间渲染页面

  1. 白屏时间包括资源申请首屏js执行
  • 资源申请:html文件、css文件、(异步的)js文件
  • js执行:例如,页面定义的const getList = () ={}函数
  1. 渲染页面包括首屏数据请求DOM渲染
  • 首屏数据请求:onMounted(() => getList())拿到数据
  • DOM渲染:将数据放在DOM中,可能会引起重排

1.1 白屏时间

1.1.1 资源加载时间

由于前端基本不会涉及到复杂的js计算,因此资源加载时间在整个白屏时间内占比最大。减少资源加载时间,一方面跟网络速度非常有关,在网速一定的情况下,优化资源体积是非常有效的策略。

1.1.1.1 打包工具

采用webpack、vite等打包工具,可以

1.1.1.2 异步加载

将首屏需要用到的资源优先加载,不需要用到的资源,等首屏需要的资源加载完成后再进行加载。 例如:在 src/router/index.js中,配置路由:

export const routes = [
    {
        path: '/',
        redirect: '/project',
    },
    {
        path: '/project',
        name: 'project',
        redirect: '/project/list',
        children: [
            {
                path: 'list',
                name: 'project-list',
                component: () => import('../views/project/ProjectList.vue'),
            },
        ],
    },
]

() => import('../views/project/ProjectList.vue')就属于异步加载。只有在路由匹配到相应的path时,才会执行回调函数,加载相应的vue文件。

1.1.1.3 安装最新的支持treeshaking的依赖

支持treeshaking当然更好,例如我们常用的lodash,直接import { debounce } from 'lodash';或者import { _ } from 'lodash';就可以导入对应的方法,但是糟糕糟糕糟糕!还是有40k。 image.png

1.1.1.4 不使用第三方库

正如刚刚所说,引入一个深拷贝方法,可能就需要40k的体积。例如在项目环境背景下,只需要深拷贝一维数组(且为简单数据类型),使用

arr1 = [...arr]
// 或者
arr1 = arr.slice()

方法,就可以进行深拷贝。而无需引入第三方库。

1.1.1.5 小图片转成base64,大图片异步加载

图片体积比较小的时候,可以将图片格式转化为base64格式,并且包入js中,减少请求资源的次数;在图片体积比较大的时候,就异步加载图片。

// webpack.config.js for Webpack 5
const path = require('path');

module.exports = {
  // ... 其他配置 ...
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif)$/i,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 8192, // 8KB 以下的图片会被转换为 base64 格式
          },
        },
        generator: {
          filename: 'images/[name].[hash:8][ext]', // 文件名格式
        },
      },
      // ... 其他规则 ...
    ],
  },
  // ... 其他配置 ...
};

1.1.2 首屏JS执行

1.2 渲染页面

1.2.1 首屏发送数据请求

1.2.2 DOM渲染

1.3 其它

还有一些收效较小的方法,例如:

  • 显示骨架屏(在index.html文件中,加入骨架)
<body>
  <div id="app">
      <span style="color:pink">祝您2024龙年大吉~</span>
  </div>
  <script type="module" src="/src/main.js"></script>
</body>
  • 将小数据量接口合并到其它接口(接口时间包括三次握手的时间,不够划算)
  • 请求并行
  • 包含大量dom情况下分批滚动渲染

2.操作速度、渲染速度

2.1 一次性操作大量dom

分批渲染,虚拟滚动,切片渲染等

2.2 不进行进行了复杂度很高的运算

循环中的操作尽量精简(其实意义不大)

2.3 vue和react的渲染性能

使用react相关技术栈

3.缓存