Vue 性能优化实践指北

时间:2020-9-21 作者:admin

说在最前面的

因为最近在来到了新的公司,在写新的项目,前端技术栈是vue,就打起了vue的性能优化的主意。
本文因为都是自己个人的一些总结的原因,所以有些地方可能难免会有些不足,还望各位大佬可以指出,我好作更改~

本文将会长期更新~

打包优化

路由懒加载

{
   path: '/home',
   name: 'home',
   component: import(/* webpackChunkName: '你要设置的chunk的name' */ '../page/home')
}

组件懒加载

这里的 /* webpackChunkName: "[request]" */中的 request表示实际解析的文件名。

const Tabs = () => import(/* webpackChunkName: "[request]" */'_c/Tabs')

export default {
    components: {
        IconList
    }
}

第三方CDN

这里想说的并不是简单的使用CDN,而是使用 externals来提取第三的依赖,并使用CDN引入。
具体使用方式将在后续提出~

Image-webpack-loader

Image-webpack-loader可以在打包的时候对图片进行优化

chainWebpack(config) {
  /** 忽略其它配置 ***/
  config
      .when(process.env.NODE_ENV !== 'development',
   /** 忽略其它配置 ***/
        config => {
          config.module
            .rule('images')
            .use('image-webpack-loader')
            .loader('image-webpack-loader')
            .options({
              mozjpeg: { progressive: true, quality: 65 },
              optipng: { enabled: false },
              pngquant: { quality: [0.65, 0.9], speed: 4 },
              gifsicle: { interlaced: false }
              // webp: { quality: 75 }
            })
    /** 忽略其它配置 ***/
        })
}

这边,我写在这个的时候遇到了如下问题:

  1. image-webpack-plugin无法安装的问题

解决方案:这边使用cnpm进行安装
2. 在打完压缩完之后,误以为图无用,需要注意,这边Png的图片,可能会用默认的预览无法查看,但是在浏览器上应该是可以查看的。
2. libpng的问题,因为这是mac电脑,我用homebrew安装过了,不清楚win中的问题

ScriptExtHtmlWebpackPlugin

这个插件是会将我拉runtimechunck之后的runtimeChunk.xx.js这样的文件内联至我们的Index.js文件之中。因为这样的一个文件是经常改变,如果不作处理的话,我们每次都需要重新请求它,如果将之进行内联的话,可以大大节省我们的时间。
配置代码如下:

config
            .plugin('ScriptExtHtmlWebpackPlugin')
            .after('html')
            .use('script-ext-html-webpack-plugin', [{
              inline: /runtime\..*\.js$/
            }])
            .end()

这段代码也是在生产打包的时候才应该执行的,所以我将之放在 chainWebpack中,这里有一点需要说明的是它最好在 splitChunk之前,同时如果你使用了 html-webpack-plugin的话,那么它也必须要是在 html-webpack-plugin之后,注意是必须!

terser-webpack-plugin

在这里,我最初的选择是 uglifyjs-webpack-plugin,这里之所以不使用它,因为它不支持es6的语法,总是会报一些奇奇怪怪的错误。然后我选选择安装和使用 terser-webpack-plugin
注意,这里里我发现了一个问题,通过查阅vue-cli4的升级变化,我发现了vue-cli4已经为我们集成了这个插件,我们只需要在webpckChain里对它进行操作就行了,具体的代码使用如下:

config.optimization.minimizer('terser').tap((args) => {
            // 去除生产环境console
            args[0].terserOptions.compress.drop_console = true
            return args
          })

我选择了在生产环境时去除我们的console

gzip

对于gzip这个并没有什么好说的,我在这里选择使用的是 compression-webpack-plugin,以下是我的具体配置

config.plugin('CompressionWebpackPlugin')
            .use('compression-webpack-plugin', [{
              filename(asset) { asset = '[file].gz[query]'; return asset },
              algorithm: 'gzip',
              test: productionGzipExtensions,
              threshold: 10240, // 只有大小大于该值的资源会被处理 10240
              minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
              deleteOriginalAssets: false // 删除原文件
            }])

可能在写法上会和你在网上看到的有所不同,但是相信我,它们的效果应该是一样的。

热更新失效

对于偶然的热更新失效的问题,这里网上也有提供许多的方法,有一些是通过安装webpack-dev-server来解决这样的问题,这里,我推荐使用如下方法:

config.resolve.symlinks(true);

代码优化

前文在对于vue-cli4的一优化已经讲了许多,接下来我想说说关于代码层面的优化。
作为一个程序员,我们应该享受 code review的过程~

v-if 与 v-show

首先明确二者的区别

  1. v-if 如果为false,则初始不会渲染,如果切换v-if的值,它总是会重新渲染
  2. v-show 不管初始值为何,都会渲染,且切换值仅仅是切换display:none这一css

在一些特定的场景下,如果某一个组件会被频繁的显示与隐藏,那么这里更推荐使用 v-show

那么,如果我们的这个组件每次我们都想要将之重新渲染,那么我们可以在这里使用v-if来触发它的强制重新渲染

在这里,如果你频繁地需要通过v-if来进行强制重新渲染的话,那么这是vue官方不建议的

vue为我们推荐了两种强制渲染视图的方法:

forceUpdate

使用这个方法的时候,我们需要注意的是,这个方法不会更新我们的计算属性,它仅仅会强制渲染我们的视图
我们需要这么做:

//main.js
import Vue from 'vue'
Vue.forceUpdate()

//component.vue
export default {
    methods:{
    componentUpdate(){
      this.$forceUpdate()
    }
  }
}

key的方式

我们可以这么使用

//component.vue
<template>
  <component-child :key='componentChildKey'></component-child>
</template>
<script>
  export default {
    data(){
        return {
        componentChildKey:1
      }
    },
    methods:{
      upDateComponentChild(){
        this.componentChildKey += 1
      }
    }
  }
</script>

善用template

对于一些不必要的外层元素,我们总是应该尽可能地使用template来替代它

v-for 与 v-if 与 key

首先,我们必须要明确,v-for与v-if不能是同级的,同时,我们使用了v-for应该为循环荐加上一个key,以提高diff的运行效率。
同时,如果我们的v-for 放在template上,那么,我们的:key不能放在template上,应该放在被包裹的最外层元素上。

而至于,为什么会提高diff的效率,将会在以后补充~

v-once

对于仅会渲染一次的元素,我们应该使用v-once
这里需要注意,如果我们在v-for中使用了v-once,那么我们必须要为这个使用的元素加上一个key

它的原理,将会在以后进行补充~

数据过滤的必要

Vue在初始化的时候会对数据进行劫持,为数据对象的每个属性添加依赖
这里,我推荐使用map映射的方式来解决这个问题,即是在获取的时候就通过map将数据“洗”一遍,剔除一些我们并不需要的数据项。

同样地数据处理问题

对于完全不需要进行响应式变动的数据,我们可以使用Object.freeze()来将之进行冻结,对于configurable属性为false的数据,vue在劫持的时候会跳过~

按需引入

类似element的需要引入这种

v-lazyload的使用

这是一个vue的懒加载的使用

对于异步请求

这里,我们如果使用了异步请求接到了一个Promise数据,我推荐使用async await的方法,并且最好是使用try catch进行包裹

对于在actions中发起请求,我们建议是如果这里不会触发state或者mutations的操作,就尽量不要将请求放到actions中。

对于watch computed 以及metheds的合理使用

  1. watch

监听某一个数据,它会影响到多个数据或者当它变化时,我们需要进行大量的其它操作

  1. computed

它是依赖于其它数据进行变化的,亦或者此项数据的计算有着极大地性能消耗

  1. methods

它是实时更新的

对于图片

我个人建议对于大图片使用Picture标签的source

其它优化

SEO优化

这里不仅仅是对SEO的优化,还会包含对于首屏白屏的一些优化

预渲染

后续完善

SSR

后续完善

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。