一、代码层面的优化

 1、v-if和v-show的使用场景
 (1)v-if适用于在运行时很少改变条件,不需要频繁切换条件的场景,属于真正的条件渲染,会确保在切换过程中,元素适当的被销毁和重建,也是惰性的;
 (2)v-show适用于频繁切换条件的场景,v-show不管初始的渲染条件是什么,元素总是会被渲染,然后根据css的display属性的值去切换显示与隐藏。

2、computed和watch的使用场景
 (1)当需要进行数值计算,并且依赖于其他数据时,应该使用computed,可以利用computed的缓存特性,避免每次获取值的时候都重新计算;
 (2)当需要在数据变化时执行异步或开销较大的操作时,应该是用watch,使用watch允许我们进行异步操作,限制我们执行该操作的频率,并且在我们得到最终结果前,设置中间值,能拿到每一次的当前值和前一次的值。

 3、v-for循环遍历必须为item添加key,key不建议设置为索引,且避免在同一个元素中同时使用v-if

4、长列表性能优化
 vue会通过Object.defineProperty()对数据进行劫持,来实现响应数据的变化,但是有时候我们的组件只需要实现对数据的展示就可以了,不会有其他修改删除的操作,所以就不需要vue来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,可以通过Object.freeze()方法来冻结一个对象,一旦被冻结的对象就不可以被修改

5、图片资源懒加载:使用vue-lazyload插件
安装:npm install vue-lazyload --save-dev
main.js引入:import VueLazyload from 'vue-lazyload'
使用:Vue.use(VueLazyload)
页面中使用,直接将img的src属性改成v-lazy:<img v-lazy="/static/img/logo.png">

6、路由懒加载:const comp = () => import('./Comp.vue')

7、第三方插件的按需引入

8、vue优化无限列表性能:使用vue-virtual-scroll-list插件
安装:npm install vue-virtual-scroll-list --save-dev
使用:<virtual-list style="height: 660px; overflow-y: auto;" :data-key="'id'" :data-sources="itemData" :data-component="itemComponent" /> (itemData:数据,itemConponent:真正展示内容的组件)

9、keep-alive的使用
利用keep-alive将不活动的组件缓存起来,在组价切换过程中,将组件的状态保存在内存中,防止重复渲染dom,减少加载时间及性能消耗,提高用户体验。

二、webpack层面的优化

1、对图片进行压缩
在 vue 项目中除了可以在 webpack.base.conf.js 中 url-loader 中设置 limit 大小来对图片处理,对小于 limit 的图片转化为 base64 格式,其余的不做操作。所以对有些较大的图片资源,在请求资源的时候,加载会很慢,我们可以用 image-webpack-loader来压缩图片;
安装:npm install image-webpack-loader --save-dev
webpack.js中配置:

{test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,use:[{loader: 'url-loader',options: {limit: 10000,name: utils.assetsPath('img/[name].[hash:7].[ext]')}},{loader: 'image-webpack-loader',options: {bypassOnDebug: true,}}]
}

2、减少es6转为es5的冗余代码
Babel插件会在es6代码转换成es5代码的时候注入一些辅助函数,例如:class HelloWebpack extends Component{...},这段代码再被转换成能正常运行的es5代码时需要以下两个辅助函数:

babel-runtime/helpers/createClass  // 用于实现 class 语法
babel-runtime/helpers/inherits  // 用于实现 extends 语法

在默认情况下,Babel会在每个输出文件中内嵌这些依赖的辅助函数代码,如果多个源代码文件都依赖于这些辅助函数,那么这些辅助函数的代码将会出现很多次,造成代码冗余,为了不然他们重复出现,可以在依赖他们时通过 require('babel-runtime/helpers/createClass')的方式导入,这样就能做到只出现一次了,babel-plugin-transform-runtime这个插件就是用来实现这个作用的,将相关的辅助函数进行替换成导入语句,从而减小babel编译出来的代码的大小;
安装:npm install babel-plugin-transform-runtime --save-dev
修改.babelrc配置文件:

"plugins": ["transform-runtime"
]

3、提取公共代码,业务代码和第三方库代码分开:webpack3中使用CommonsChunkPlugin插件、webpack4中使用optimization.splitChunks插件

CommonsChunkPlugin插件详细参数:
name: 给这个包含公共代码的chunk命名
filename: 命名打包后生成的js文件
minChunks: 公共代码的判断标准,某个js模块被多少个文件引入才算公共代码,默认为1,我们可以为2, 也就是说如果
一个文件被其他页面引入了超过了2次及以上,就可以认为该文件就是公用代码。
chunks: 表示需要在哪些chunk(配置中entry的每一项)里寻找公共代码进行打包,默认不设置,那么它的寻找范围为所有的chunk;

如果项目中没有把每个页面的第三方库和公共模块提取出来,则项目会存在以下问题:
a、相同的资源被重复加载,浪费客户的流量和服务器的成本
b、每个页面需要加载的资源太大,导致网页首屏加载缓慢,影响用户体验
所以我们需要将多个页面的公共代码抽离成单独的文件,来优化以上问题,webpack专门内置了用于提取多个chunk中的公共部分的插件CommonsChunkPlugin,我们在项目中CommonChunkPlugin的配置如下:

// 所有在 package.json 里面依赖的包,都会被打包进 vendor.js 这个文件中。
new webpack.optimize.CommonsChunkPlugin({name: 'vendor',minChunks: function(module, count) {return (module.resource &&/\.js$/.test(module.resource) &&module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0);}
}),
// 抽取出代码模块的映射关系
new webpack.optimize.CommonsChunkPlugin({name: 'manifest',chunks: ['vendor']
})

optimization.splitChunks参数详解:

(1)、cacheGroups:splitChunks配置的核心,对代码的拆分规则全在cacheGroups缓存组里配置,缓存组里的每一个属性都是一个配置规则,可以自己定义属性名称,属性值是一个对象,放的是对一个代码拆分规则的描述,有两个属性:name和chunks;
name:提取出来的公共模块将会以这个名称命名,可以不配置,如果不配置的话,就会生成默认的文件名
chunks:指定哪些类型的chunks参与拆分,值可以是string也可以是函数,如果是string的话,可以有三个值:all、async、initial,all代表所有模块,async代表异步加载的,initial代表初始化时就能获取的模块,如果是函数,则可以通过chunks的name属性等进行更详细的筛选

(2)、miniChunks:splitChunks是自带默认配置的,而缓存组默认会继承这些配置,其中有个miniChunks属性,它是控制每个模块什么时候被抽离出去:当模块被不同的entry引用的次数大于等于这个配置的值时,才会被抽离出去,默认值是1,也就是任何模块都会被抽离出去,(入口模块也会被webpack引入一次)

(3)、miniSize:提取的chunk的最小大小

(4)、priority:值为数值型,可以是负数,作用是当拆分组中设置多个拆分规则,且某个模块符合多个规则时,则通过优先级属性priority来决定使用哪个拆分规则,优先级高者执行

(5)、test:用于进一步控制缓存组选择的模块,可以是一个正则表达式,也可以是一个函数,可以匹配模块的绝对路径或chunk名称,匹配chunk名称时将选择chunk中所有的模块

例子:

optimization: {splitChunks: {minSize: 30,  //提取出的chunk的最小大小cacheGroups: {default: {name: 'common',chunks: 'initial',minChunks: 2,  //模块被引用2次以上的才抽离priority: -20},vendors: {  //拆分第三方库(通过npm|yarn安装的库)test: /[\\/]node_modules[\\/]/,name: 'vendor',chunks: 'initial',priority: -10}}}
}

4、构建结果输出分析:webpack-bundle-analyzer
webpack输出的代码可读性很差,而且文件非常大,为了简单、直观的分析输出结果,可以使用分析工具,以图形的形式将结果更直观的展示出来
安装:npm install --save-dev webpack-bundle-analyzer
webpack.config.js配置:

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
plugins: [new BundleAnalyzerPlugin()]

package.json的"scripts"中添加:

"dev": "webpack --config webpack.config.js --progress"

执行语句生成分析报告:npm run dev

5、打包去掉console.log等语句:uglifyjs-webpack-plugin
安装:npm install uglifyjs-webpack-plugin
webpack.config.js中配置:

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports = {configureWebpack: (config) => {if (process.env.NODE_ENV === 'production') {return {plugins: [//打包环境去掉console.lognew UglifyJsPlugin({uglifyOptions: {compress: {warnings: false,drop_console: true,  //注释consoledrop_debugger: true, //注释debuggerpure_funcs: ['console.log'], //移除console.log},},}),],}}}
}

三、基础的web技术优化

1、开启gzip压缩:compression-webpack-plugin
安装://新版本不太兼容,推荐这个版本
npm install compression-webpack-plugin@6.1.1 --save-dev
在webpack.config.js中使用:

const CompressionWebpackPlugin = require('compression-webpack-plugin')
new CompressionWebpackPlugin({filename: '[path][base].gz',algorithm: 'gzip',  // 压缩算法,官方默认压缩算法是gziptest: /\.js$|\.css$|\.html$|\.eot$|\.woff$/, // 使用gzip压缩的文件类型threshold: 10240,  // 以字节为单位压缩超过此大小的文件,默认是10240minRatio: 0.8,  // 最小压缩比率,默认是0.8})

后端配置:
(1)Nginx:主要是下方的gizp配置哦,直接复制粘贴就可以使用啦,亲测有效哦

server{//开启和关闭gzip模式gzip on;//gizp压缩起点,文件大于2k才进行压缩;设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。 默认值是0,不管页面多大都压缩。建议设置成大于2k的字节数,小于2k可能会越压越大。gzip_min_length 2k;// 设置压缩所需要的缓冲区大小,以4k为单位,如果文件为7k则申请2*4k的缓冲区 gzip_buffers 4 16k;// 设置gzip压缩针对的HTTP协议版本gzip_http_version 1.0;// gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间gzip_comp_level 2;//进行压缩的文件类型gzip_types text/plain application/javascript text/css application/xml;// 是否在http header中添加Vary: Accept-Encoding,建议开启gzip_vary on;
}

(2)express的中间件:compression,主要用于进行gzip压缩,通常用于web性能优化,能对文本内容进行压缩,一般用于html文件;
安装:npm install compression --save
使用:

var compression = require('compression');
const app = express()
// 启用gzip
app.use(compression());

2、浏览器缓存
对静态资源进行缓存,根据是否需要重新向服务器发起请求来分类,将http请求分为强制缓存和对比缓存

3、CDN的使用
浏览器从服务器上下载css、js和图片等文件时都要和服务器连接,而大部分的服务器的带宽都有限,如果超过限制,网页就半天反应不过来,而CDN可以通过不同的域名来加载文件,从而使下载文件的并发连接数大大增加,且CDN具有更好的可用性,更低的网络延迟和丢包率

4、使用Chrome Performance查找性能瓶颈
Chrome的Performance面板可以录制一段时间内的js执行细节及时间,步骤:
a、打开Chrome开发者工具,点进Performance面板
b、点击Record开始录制
c、刷新页面或展开某个节点
d、点击stop停止录制,就可以查看了

四、网络层面的优化

1、重复请求的取消
第一次请求还没回来之前就进行了第二次同样的请求时,就应该把第二次请求取消掉,防止重复请求;
在axios请求中进行封装,采用拦截器进行处理,首先实现三个方法,当请求方式、请求URL和携带参数都一致时,就可以认为是同样的请求,因此在发起请求时,可以根据当前的请求方式、请求地址和携带的参数来生成一个唯一的key,同时为每个请求创建一个专属的cancelToken,然后将key和cancelToken函数以键值对的形式保存到map对象中,使用map对象的好处就是可以快速判断是否有重复的请求:

    // 用于根据当前的请求信息生成请求的keygenerateReqKey(config) {const { url, method, params, data } = config;return [url, method, qs.stringify(params), qs.stringify(data)].join("&");},// 用于将当前请求信息添加到pendingRequest对象中PendingRequest = new Map(),addPendingRequest(config) {const requestKey = this.generateReqKey(config)config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {if(!this.PendingRequest.has(requestKey)) {this.PendingRequest.set(requestKey, cancel)}})},// 检查是否有重复的请求,若存在则需要取消已经发出的请求removeRequest(config) {const requestKey = this.generateReqKey(config)if (this.PendingRequest.has(requestKey)) {const CancelToken = this.PendingRequest.get(requestKey)CancelToken(requestKey)this.PendingRequest.delete(requestKey)}}

因为需要对所有的请求都进行处理,所以直接在拦截器来实现取消重复请求的操作,
(1)请求拦截器:作用是在请求发送前统一执行某些操作,比如在请求头中添加token字段
(2)响应拦截器:作用是在接收到服务器响应后统一执行某些操作,比如根据不同的状态码进行不同的响应操作

    axios.interceptors.request.use(config => {// 检查是否有重复的请求this.removeRequest(config)// 把当前请求添加到PendingRequest对象中this.addPendingRequest(config)const token = localStorage.getItem('token')if(token) {config.headers.Authorization = `Bearer ${token}`}return config}, error => {return Promise.reject(error)})axios.interceptors.response.use(res => {// 从PendingRequest对象中移除请求this.removeRequest(res.config)const {data} = config;return data}, error => {// 从PendingRequest对象中移除请求this.removeRequest(error.config)return Promise.reject(error)})

2、限制失败请求重试的次数,避免无效请求过多,导致大量的资源消耗

//在main.js设置全局的请求次数,请求的间隙
axios.defaults.retry = 4;  // 请求次数
axios.defaults.retryDelay = 1000;  // 请求间隙
//响应拦截
axios.interceptors.response.use(undefined, function axiosRetryInterceptor(err) {var config = err.config;// 如果配置不存在或未设置重试选项,则返回错误信息if(!config || !config.retry) return Promise.reject(err);// 设置变量即跟踪重试次数config.__retryCount = config.__retryCount || 0;// 检查我们是否已经超过了总重试次数if(config.__retryCount >= config.retry) {// 返回错误信息return Promise.reject(err);}// 重试次数加1config.__retryCount += 1;// 创建延时器等待发送重试请求var backoff = new Promise(function(resolve) {setTimeout(function() {resolve();}, config.retryDelay || 1);});// 返回调用AXIOS来重试请求return backoff.then(function() {return axios(config);});
});

3、善用缓存,减小网络请求的次数
4、断网处理:
在vuex中存放network的状态,根据network的状态判断是否需要加载断网组件,断网情况就加载断网组件,不加载对应的页面组件,点击刷新,就跳转到refresh页面然后立即返回来实现重新获取数据,所以新建refresh.vue,在beforeRouteEnter钩子中返回当前页面

// 断网页面
<template>  <div id="app">    <div v-if="!network">      <h3>我没网了</h3>      <div @click="onRefresh">刷新</div>      </div>    <router-view/>      </div>
</template><script>import { mapState } from 'vuex';export default {  name: 'App',  computed: {    ...mapState(['network'])  },  methods: {    // 通过跳转一个空页面再返回的方式来实现刷新当前页面数据的目的onRefresh () {      this.$router.replace('/refresh')    }  }}
</script>
在refresh.vue页面中:
// refresh.vue
beforeRouteEnter (to, from, next) {next(vm => {            vm.$router.replace(from.fullPath)        })
}

Vue项目性能优化方案相关推荐

  1. Vue 项目性能优化方案

    前言 Vue 框架通过数据双向绑定和虚拟 DOM 技术,帮我们处理了前端开发中最脏最累的 DOM 操作部分, 我们不再需要去考虑如何操作 DOM 以及如何最高效地操作 DOM:但 Vue 项目中仍然存 ...

  2. vue项目性能优化——断点续传

    vue项目性能优化 用户上传文件的时候,如果文件过大,那么上传可能就会很耗时.而且一旦上传的过程中发生了网络中断,那上传就前功尽弃了.为了提高用户的体验,我们可以选择断点续传,也就是把文件切分成小块后 ...

  3. Vue项目性能优化篇

    Vue项目性能优化是个老生常谈的问题了,本人开发过程中也查过很多关于Vue项目优化的文章,每篇文章说的都差不多,本章我就结合我的心得和大家的智慧做一个总结. 1.懒加载 懒加载应该是提高性能的最简单有 ...

  4. 前端Vue 项目性能优化

    前言 Vue 框架通过数据双向绑定和虚拟 DOM 技术,帮我们处理了前端开发中最脏最累的 DOM 操作部分, 我们不再需要去考虑如何操作 DOM 以及如何最高效地操作 DOM:但 Vue 项目中仍然存 ...

  5. 接手同事vue项目两个月的血和泪,关于vue项目性能优化,缩短首屏加载时间

    最近接手了别人做的vue项目,项目跑起来后,有些页面很卡,首屏加载也慢,打包速度也慢.于是,研究了很久vue的项目性能优化,下面我将从两个部分来详解vue项目的性能优化: 代码优化 webpack打包 ...

  6. 收藏这些vue项目性能优化方式,总有一天能用上

    vue项目如何进行性能优化?下面本篇文章给大家分享一些vue项目一定会用到的性能优化方法,希望对大家有所帮助! 提起性能优化 很多人眼前浮现的面试经验是不是历历在目呢?反正,性能优化在我看来他永远是前 ...

  7. vue项目性能优化(图片优化)

    一.图片保存阶段 ps 或 sketch 等图片,保存时或保存后,使用photoshop .jpg 图片选择 "连续" .png图片选择 "优化" 二. 图片压 ...

  8. 前端Vue项目打包性能优化方案

    文章目录 一.前言 二.优化方案 1丶路由懒加载(代码分割) 2丶第三方插件按需加载 3丶常用插件库使用CDN加速 4.gzip压缩 5.打包不生成map文件 三.工具推荐 可视化分析包大小 总结 一 ...

  9. vuejs项目性能优化 - 总结篇

    首页等页面加载慢?打包编译后css/js文件过大?试试压缩.路由懒加载等技术 打包编译后,过大的文件如:app.css.app.js.vendor.js 本着 "开发环境".&qu ...

最新文章

  1. MPB:生态环境中心陈保冬组-基于高通量测序技术的丛枝菌根真菌多样性研究方法...
  2. Coursera algorithm II PA4
  3. sliverlight--无法启动调试。
  4. 【Zabbix】CentOS6.9系统下部署Zabbix-server 3.0
  5. [转载]今天安装sql2000,老是出挂起的错误。所以找了找看见了这个方法。
  6. 讲讲 Python Launcher 是什么鬼东西?
  7. android 导入so库
  8. LNMP服务跨省迁移的解决方案
  9. filepath直接指定到文件名吗_PyTest运行指定的测试集
  10. 面向对象:包装类、对象处理、类成员
  11. 浅谈python MRO与Mixin模式
  12. rabbitmq接口异常函数方法_[项目更新] 集成RabbitMQ队列与EventBus总线
  13. vue中对话框关闭以后清空对话框中input,select内容
  14. java多继承_为什么 Java 不支持类多重继承?
  15. 集合set中的基数cardinality是什么意思
  16. 对算法的认识——逻辑回归
  17. 机器学习刻画股票市场结构和可视化——以上证50成分股为例
  18. 统信UOS系统安装详细教程(小白也能装系统啦~)
  19. APP性能测试——启动时间
  20. antv图例出现分页_自定义图例组件

热门文章

  1. idea出现Can not set int field xxx to java.lang.Long 错误
  2. 常用的正则表达式判断手机号邮箱等
  3. 参考霍兰德人格分析雷达图的思路来设计一组学生八门课的成绩雷达图
  4. 重生强化【Reincarnating RL】论文梳理
  5. 理解react生命周期,以及react生命周期的使用场景
  6. OSG计算并绘制模型中每一个三角面片的法向量
  7. UI配色参考网站收集
  8. VC编程工具的灵活使用实验报告
  9. i春秋2020新春公益赛 GYCTF有关SQL注入题复现
  10. 编程中「缺省」是什么意思?