您现在的位置是:首页 >其他 >前端项目性能优化合集网站首页其他

前端项目性能优化合集

xiaofiy 2024-06-19 12:01:02
简介前端项目性能优化合集

本文将从三个角度(页面渲染,打包优化,总体优化)分析前端性能优化的一些方案

页面渲染

1. 减少页面重绘(repaint)和回流(reflow)

减少使用 css 属性简写,如:用border-width, border-style, border-color代替border。因为css简写把所有值初始化为initial,尽量不使用属性简写可以最小化重绘(repaint)和回流(reflow),(实际工作中,由于css简写带来的性能影响微乎其微,再加上css全都展开写还会增加code size,另外css简写还能解决一些样式覆盖的问题)

  • 通过修改className批量修改元素样式;
  • 复杂的动画元素定位要设置为 fixed 或 absoult,避免引起回流;
  • 不使用table布局(table元素一旦触发回流就会导致table里所有的其它元素回流);
  • DOM 元素上下移动用用translate替代top修改
  • 需要创建多个DOM节点时,使用DocumentFragment一次性创建。
  • css3硬件加速(GPU加速),它可以让transform、opacity、filters这些动画不会引起回流重绘。对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能(但是不能滥用,会导致性能问题)。
  • 元素适当地定义高度或最小高度,否则元素的动态内容载入时,会出现页面元素的晃动或位置,造成回流(比如图片要定义宽高,避免页面塌陷,同时减少回流);
  • 减少使用层级较深的选择器,或其他一些复杂的选择器,以提高CSS渲染效率;
  • 在大量修改元素样式时,可以先用display: none将其隐藏,修改完再设置为display: block,这样只会造成两次回流;

2. 图片压缩,图片分割,精灵图

图片压缩:开发中比较重要的一个环节,现在很多图床工具都自带压缩功能的。如果需要自己压缩的话,可以在tinyPng 网站压缩一下;

  • 图片分割:如果页面需要加载一张效果图,比如真机渲染图,UI设计师不允许压缩的时候,我们就可以将图片分割,然后再用css布局将图片拼接到一起。
  • 精灵图:与图片分割相反,精灵图是将很多小图片合并到一张大图里,这样加载页面的时候,只需要加载一张图片,就可以加载出来所有的页面元素。这样在一定程度上提高了页面加载速度。而我们使用精灵图的方式,也是通过定位,即通过background-position来移动背景图,从而显示出我们想要显示出来的部分。
    但是精灵兔有个很大的不足,那就是牵一发而动全身,因为我们使用精灵图需要准确测量每个元素的位置,一旦要调整页面,将会是一项很麻烦的工作。

3. 字体包压缩

问题描述: 在做类似活动h5的时候,难免需要使用 @font-face 接口引入一些字体包,以达到丰富的页面效果。但是完整的字体包文件一般都很好几兆,加载页面时,不仅会阻塞页面渲染,还会导致文字开始不会显示,直至字体包加载完才会显示文字。

解决方式: 可以使用font-spider字蛛将要使用到的文字提取出来。

4. 懒加载/预加载资源

懒加载: 简言之就是只有当图片出现在浏览器的可视区域内时,才加载图片让图片显示出来(在此之前可以将所有图片元素的路径全都统一设置成一张1*1px的占位图)。
判断图片出现在浏览器可视区域的方法:图片距离顶部的高度(offsetTop) - 页面被卷去的高度(scrollTop) 〈= 浏览器的可视区域的高度(innerHeight)

预加载: Resource Hints(资源预加载)包括预连接、资源与获取、资源预渲染等。
预加载的思路有如下两个:
当前将要获取资源的列表;
通过当前页面或应用的状态、用户历史行为或 session 预测用户行为及必需的资源.
实现Resource Hints的方法有很多种,可分为基于 link 标签的 DNS-prefetch、subresource、preload、 prefetch、preconnect、prerender,和本地存储 localStorage。

打包优化

1. webpack优化resolve.alias配置(vite同理)

resolve.alias 配置通过别名来将原导入路径映射成一个新的导入路径。
可以起到两个作用:1.起别名;2.减少查找过程

resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },

2. webpack优化resolve.extensions配置(vite同理)

resolve.extensions 代表后缀尝试列表,它也会影响构建的性能,默认是:
extensions: [‘.js’, ‘.json’]
例如遇到require(‘./data’)这样的导入语句时,Webpack会先去寻找./data.js文件,如果该文件不存在就去寻找./data.json文件,如果还是找不到就报错。
【所以后缀尝试列表要尽可能的小,不要把项目中不可能存在的情况写到后缀尝试列表中,频率出现最高的文件后缀要优先放在最前面,以做到尽快的退出寻找过程。】
在源码中写导入语句时,要尽可能的带上后缀,从而可以避免寻找过程。例如在你确定的情况下把require(‘./data’)写成require(‘./data.json’)。

resolve: {
    extensions: ['.js', '.vue', '.json'],
}

3. webpack缩小loader范围

loader是很消耗性能的一个点,我们在配置loader的时候,可以使用include和except来缩小loader执行范围,从而优化性能。

{
    test: /.svg$/,
    loader: 'svg-sprite-loader',
    include: [resolve('src/icons')]
 },

4. split chunks代码分包

在没配置任何东西的情况下,webpack 4 就智能的帮你做了代码分包。入口文件依赖的文件都被打包进了main.js,那些大于 30kb 的第三方包,如:echarts、xlsx、dropzone等都被单独打包成了一个个独立 bundle。
其它被我们设置了异步加载的页面或者组件变成了一个个chunk,也就是被打包成独立的bundle。
它内置的代码分割策略是这样的:
新的 chunk 是否被共享或者是来自 node_modules 的模块;
新的 chunk 体积在压缩之前是否大于 30kb;
按需加载 chunk 的并发请求数量小于等于 5 个;
页面初始加载时的并发请求数量小于等于 3 个;

splitChunks({
  cacheGroups: {
    vendors: {
      name: `chunk-vendors`,
      test: /[\/]node_modules[\/]/,
      priority: -10,
      chunks: 'initial',
    },
    dll: {
      name: `chunk-dll`,
      test: /[\/]bizcharts|[\/]@antv[\/]data-set/,
      priority: 15,
      chunks: 'all',
      reuseExistingChunk: true
    },
    common: {
      name: `chunk-common`,
      minChunks: 2,
      priority: -20,
      chunks: 'all',
      reuseExistingChunk: true
    },
  }
})

vite配置代码如下:

build: {
    rollupOptions: {
      output: {
        chunkFileNames: 'js/[name]-[hash].js',  // 引入文件名的名称
        entryFileNames: 'js/[name]-[hash].js',  // 包的入口文件名称
        assetFileNames: '[ext]/[name]-[hash].[ext]' // 资源文件像 字体,图片等
      }
    }
 }

5. tree shaking

tree shaking(摇树)。望文生义,它是用来清除我们项目中的一些无用代码,它依赖于ES中的模块语法得以实现。 比如日常使用lodash的时候:
import _ from ‘lodash’
如果如上引用lodash库,在构建包的时候是会把整个lodash包打入到我们的bundle包中的。
import _isEmpty from ‘lodash/isEmpty’;

如果如上引用lodash库,在构建包的时候只会把isEmpty这个方法抽离出来再打入到我们的bundle包中。
tree shaking可以大大减少包体积,是性能优化中的重要一环。
在 vite 和 webpack4.x 中都已经默认开启tree-shaking。

6. vite关闭一些打包配置项()

webpack也有类似的配置,自行查阅

build: {
terserOptions: {
compress: {
//生产环境时移除console
drop_console: true,
drop_debugger: true,
},
},
//关闭文件计算
reportCompressedSize: false,
//关闭生成map文件 可以达到缩小打包体积
sourcemap: false, // 这个生产环境一定要关闭,不然打包的产物会很大
}

总体优化

1. SSR服务端渲染

SSR(Server Side Rendering),即服务端渲染。它指的是渲染过程在服务端完成,最终的渲染结果 HTML 页面通过 HTTP 协议发送给客户端,又叫“同构“。

SSR主要带来的好处就是 SEO 和首屏加载速度大大提高

2. Brotli 算法压缩

Brotli 压缩算法 是 Google 2015年推出的无损压缩算法。

启用 Brotli 压缩算法,对比 Gzip 压缩 CDN 流量再减少 20%。
针对常见的 Web 资源内容,Brotli 的性能相比 Gzip 提高了 17-25%;
当 Brotli 压缩级别为 1 时,压缩率比 Gzip 压缩等级为 9(最高)时还要高;
在处理不同 HTML 文档时,Brotli 依然能够提供非常高的压缩率。
兼容性:目前除了 IE 和 Opera Mini 之外,几乎所有的主流浏览器都已支持 Brotli 算法。

vite项目开启 brotli 压缩:
使用 vite-plugin-compression (opens new window)对平台进行 gzip 或者 brotli 压缩,nginx 对这两种压缩模式都支持,压缩后部署到 nginx 将极大提高网页加载速度。
修改 .env.production 文件,设置 VITE_COMPRESSION 全局变量即可

# 不开启压缩,默认
VITE_COMPRESSION = "none"
//以下配置压缩时不删除原始文件的配置
开启 gzip 压缩,
VITE_COMPRESSION = "gzip"

开启 brotli 压缩
VITE_COMPRESSION = "brotli"

# 同时开启 gzip 与 brotli 压缩
VITE_COMPRESSION = "both"

//以下配置压缩时删除原始文件的配置
开启 gzip 压缩
VITE_COMPRESSION = "gzip-clear"

开启 brotli 压缩
VITE_COMPRESSION = "brotli-clear"

# 同时开启 gzip 与 brotli 压缩
VITE_COMPRESSION = "both-clear"

3. 缓存

缓存的原理就是更快读写的存储介质+减少IO+减少CPU计算=性能优化。而性能优化的第一定律就是:优先考虑使用缓存。
缓存的主要手段有:浏览器缓存、CDN、反向代理、本地缓存、分布式缓存、数据库缓存。

4. Ajax可缓存

Ajax在发送的数据成功后,为了提高页面的响应速度和用户体验,会把请求的URL和返回的响应结果保存在缓存内,当下一次调用Ajax发送相同的请求(URL和参数完全相同)时,它就会直接从缓存中拿数据。
在进行Ajax请求的时候,可以选择尽量使用get方法,这样可以使用客户端的缓存,提高请求速度。

5.组件按需引入

使用第三方组件库时,要按需引入,例如import { Button } from ‘element-plus’;

6.动态加载

使用import()动态引入的语法引入一些第三方库和组件,例如我们在测试环境下开启 vconsole 调试:

if (location.host !== '正式环境域名') {
  import('@/utils/vconsole')
}

7.组件异步加载

// 1. import懒加载
() => import('@/pages/xxx.vue')
// 2. 使用require
resolve => require(['@/pages/xxx.vue'], resolve),

8.路由懒加载

{
  path: '/index',
  name: 'index',
  component: () => import('@view/xxx.vue'),
  //或者 component: require(['@/view/xxx.vue'], resolve), 
  meta: { title: '首页' }
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。