vue 常见的优化手段

322 阅读8分钟
  • 一般情况下,都是通过什么手段或者方法来进行性能分析的
  • 长列表优化(vue-vitual-scoll-list和vue-virtual-scroller)
  • 突破浏览器并发限制方法有哪些?
  • 在项目中如何使资源用缓存最合理?
  • canvas 合成图片或者或者画视频生成base64时候卡顿

性能优化总结:减少请求次数、减小资源大小、提高响应和加载速度、优化资源加载时机、优化加载方式。

主要从两个方面进行优化 构建优化、网络资源优化

构建优化

Gzip

gzip 压缩效率非常高,通常可以达到 70% 的压缩率,也就是说,如果你的网页有 30K,压缩之后也就10K左右。compression-webpack-plugin,这个插件不仅能够gzip压缩,还能够去除console.log、debugger,gzip压缩需要服务端配合开启

const CompressionPlugin = require('compression-webpack-plugin')

configureWebpack: config => {
  config.plugins.push(new CompressionPlugin())
}

去除 console.log

线上不应该看到日志信息,所以需要去掉console.log, 而有时候我们忘记手动去掉,所以用以下方式可以做到自动去除

 configureWebpack: config => {
   const TerserPlugin = require('terser-webpack-plugin')
   config.optimization.minimizer.push(
     new TerserPlugin({
       extractComments: false,
       terserOptions: { compress: { drop_console: true } },
     })
   )
 }
 
// minimizer: [
//   new UglifyJsPlugin({
//     uglifyOptions: {
//       compress: {
//         drop_debugger: true, // debugger
//         drop_console: true,
//         pure_funcs: ['console.log'] // 移除console
//       }
//     }
//   })
// ]

去除 SourceMap

module.exports = {
  productionSourceMap: false,
}

CDN减少打包体积

CDN的全称是Content Delivery Network,即内容分发网络。CDN的通俗理解就是网站加速,不仅能减少打包体积,还能增加网站相应速度。(浏览器对同一个域名的资源请求并发有限制,如果资源比较多,可以用多个域名。)

configureWebpack: config => {
    config.externals = {
    	'Vue': 'Vue',
        'element-ui': 'element-ui'
    }
}

路由懒加载(按需加载)

主要解决首屏加载速度,提高用户体验,要注意的是,要关闭prefetch,这个配置默认是打开的,说的是在空闲时期加载,其实还是会多少影响首屏加载速度.

chainWebpack: config => {
  config.plugins.delete('prefetch')
},

资源和并与压缩

减少http请求数量

比如嵌套路由,一个模块可以编译成一个chunkname,本来也不是特别大。这样可以达到减少请求次数.

第三方插件的按需引入

我们在项目中经常会需要引入第三方插件,如果我们直接引入整个插件,会导致项目的体积太大,我们可以借助 babel-plugin-component ,然后可以只引入需要的组件,以达到减小项目体积的目的。以下为项目中引入 element-ui 组件库为例:

  • 1)首先,安装 babel-plugin-component npm install babel-plugin-component -D
  • 2)然后,将 .babelrc 修改为:
{
  "presets": [["es2015", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

- 3)在 main.js 中引入部分组件:

import Vue from 'vue';
import { Button, Select } from 'element-ui';

 Vue.use(Button)
 Vue.use(Select)

提取公共代码

Webpack 内置了专门用于提取多个Chunk 中的公共部分的插件 split-chunks-plugin,根据不同需求可以做不同的配置:

configureWebpack: config => {
    /** 去掉console.log debugger sourceMap*/
    console.log()
    config.optimization = {
      splitChunks: {  
        chunks: 'async', // 代码分割时对异步代码生效,all:所有代码有效,inital:同步代码有效
        minSize: 30000, // 代码分割最小的模块大小,引入的模块大于 30000B 才做代码分割
        maxSize: 0, // 代码分割最大的模块大小,大于这个值要进行代码分割,一般使用默认值
        minChunks: 1, // 引入的次数大于等于1时才进行代码分割
        maxAsyncRequests: 6, // 最大的异步请求数量,也就是同时加载的模块最大模块数量
        maxInitialRequests: 4, // 入口文件做代码分割最多分成 4 个 js 文件
        automaticNameDelimiter: '~', // 文件生成时的连接符
        automaticNameMaxLength: 30, // 自动生成的文件名的最大长度
        cacheGroups: {  
          vendors: {  
            name: "chunk-vendors1111",  //  
            test: /[\\/]node_modules[\\/]/,  
            priority: -20, // 分离规则的优先级,优先级越高,则优先匹配。
            chunks: "initial"  
          },
          'element-ui': {
            name: 'chunk-elementUI', // split elementUI into a single package
            priority: -5, // the weight needs to be larger than libs and app or it will be packaged into libs or app
            test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
          },
        },
      }
    }
  }
}

网络资源优化

缓存 这是一个链接

合理使用缓存

缓存可以说是性能优化中最高效的一种手段

三级缓存:

  • 先查找内存,如果内存中存在,从内存中加载;
  • 如果内存中未查找到,选择硬盘获取,如果硬盘中有,从硬盘中加载;
  • 如果硬盘中未查找到,那就进行网络请求;
  • 加载到的资源缓存到硬盘和内存;

HTTP状态码:

  • 200 form memory cache 不访问服务器,一般已经加载过该资源且缓存在了内存当中,直接从内存中读取缓存。浏览器关闭后,数据将不存在(资源被释放掉了),再次打开相同的页面时,不会出现from memory cache。

  • 200 from disk cache 不访问服务器,已经在之前的某个时间加载过该资源,直接从硬盘中读取缓存,关闭浏览器后,数据依然存在,此资源不会随着该页面的关闭而释放掉下次打开仍然会是from disk cache。

  • 304 Not Modified 访问服务器,发现数据没有更新,服务器返回此状态码。然后从缓存中读取数据。

一、vue的所有资源修改后打包出来的名称都会改变,所以可以使用强缓存,对css、js、png、ttf、jpg等

  

location ~* \.(css|js|png|jpg|jpeg|gif|gz|svg|mp4|ogg|ogv|webm|htc|xml|woff)$ {
            access_log off;
            add_header Cache-Control max-age=604800;
        }

二、html文件每次编译名称不会改变,所以使用协商缓存,html文件有改动就会立即更新, max-age=no-cache代表直接进入协商缓存,文件改动会自动更新,不改动会返回304, 确保index.html 里面加载的js css等资源确保每次更新完之后都会拿到最新的资源

location ~* \.(html)$ {
            access_log off;
            add_header  Cache-Control  max-age=no-cache;
        }

HTTP2

特性

  • 多路复用,无需多个TCP连接,因为其允许在单一的HTTP2连接上发起多重请求,因此可以不用依赖建立多个TCP连接。

  • 二进制分帧,将所有要传输的消息采用二进制编码,并且会将信息分割为更小的消息块。

  • 头部压缩,用HPACK技术压缩头部,减小报文大小

  • 服务端推送,服务端可以在客户端发起请求前发送数据,换句话说,服务端可以对客户端的一个请求发送多个相应,并且资源可以正常缓存。 HTTP客户端一般对同一个服务器的并发连接个数都是有限制的。

    实际上,浏览器确实使用并行连接,但它们将并行连接的总数限制为少量(通常为四个)。服务器可以自由地关闭来自特定客户端的过多连接。

一些主流浏览器对HTTP 1.1和HTTP 1.0的最大并发连接数目,可以参考如下表格: ngnix 相关配置

server {
    listen 443 ssl http2;
}

能够很好的利用服务器宽带性能

注意:使用 http2 的前提是必须是 https

资源预加载

对当前页面需要的资源,使用 preload 进行预加载,对其它页面需要的资源进行 prefetch 预加载

preload

preload 页面加载的过程中,在浏览器开始主体渲染之前加载。

<!-- 对sty1e.cs5和 index.js进行pre1oad预加载 -->
<link rel="preload" href="style.css" as="style">
<link rel="preload" href="index.js" as="script">

prefetch

prefetch 页面加载完成后,利用空闲时间提前加载。

<!--对资源进行 prefetch预加载-->
<link rel="prefetch" href="next.css">
<link rel="prefetch" href="next.js">

注意:vue-cli 默认开启 prefetch ,可在 vue.config.js 中全局禁用 prefetch ,再针对指定模块开启。

chainWebpack: config => {
  config.plugins.delete('prefetch')
}

dns-prefetch

页面加载完成后,利用空闲时间提前加载。

<link rel="dns-prefetch" href="//example.com">

异步无阻塞加载JS

页面加载完成后,利用空闲时间提前加载。 异步加载 js 文件,并且不会阻塞页面的渲染。

defer

<script src="d.js" defer></script>
<script src="e.js" defer></script>
  • 不阻止解析 document, 并行下载 d.js, e.js
  • 即使下载完 d.js, e.js 仍继续解析 document
  • 按照页面中出现的顺序,在其他同步脚本执行后,DOMContentLoaded 事件前 依次执行 d.js, e.js。

async

<script src="b.js" async></script>
<script src="c.js" async></script>
  • 不阻止解析 document, 并行下载 b.js, c.js
  • 当脚本下载完后立即执行。(两者执行顺序不确定,执行阶段不确定,可能在 DOMContentLoaded 事件前或者后 )

图片优化

  • 格式选择 png、svg、webp
  • 雪碧图(优点: 减少网站的http请求数量 缺点: 整张图片比较大时,加载速度比较慢)雪碧图制作工具 spritecow
  • base64 (图标大小最好小于5kb)

用户体验优化

  • 菊花loading,在加载资源过程之中,可以提供loading。此菊花loading不是那菊花。所以可以自由选择自己喜欢的菊花。
  • 骨架屏幕 在首屏加载资源较多,可能会出现白屏和闪屏的情况(antv)

如果追求极致的性能瓶颈 可以关注chrome->performance工具

具体内容可以参考这是一个参考链接

减少css重排重绘

触发reflow的属性

布局定位字体排版
widthtoptext-align
heightrightoverflow-y
paddingbottomfont-weight
marginleftoverflow
displayfloatfont-family
border-widthclearline-height
borderpositionvertical-align
min-heightfont-sizewhite-space

触发repaint的属性

  • border-style
  • border-radius
  • visibility
  • text-decoration
  • outline-color
  • outline
  • outline-style
  • outline-width
  • background
  • background-image
  • background-position
  • background-repeat
  • background-size
  • box-shadow
  • color