记录一次Vue大型项目高性能优化

发表于 3年以前  | 总阅读数:975 次

一、背景

目前公司的电子合同采用表单设计器+合同业务配合实现,做了半年多后终于上线,但是下边员工普遍反映卡顿,甚至卡死,爆栈。尤其是新增和修改合同页面,因为这部分数据量大,逻辑复杂,很容易崩溃,所以决定进行性能优化。

二、业务场景介绍

先来了解一下我们是怎么实现:

1 . 因为我们公司合同变换频繁,条款之间还有逻辑,所以做了个基础服务(说白了就是组件库),为合同提供模板

2 . 表单设计器作为基础服务,打包成了组件库,嵌入到合同项目,包括合同生成组件(拖拽生成合同模板)和合同预览组件(加载数据库中的合同模板数据)

3 . 合同项目有一个模块管理页面,可以对多个模板进行维护,比如可以选择启用哪个模板。

4 . 合同的管理员负责维护模板,可以用表单设计器拖拽生成合同模板,提交后落入数据库,每个合同类型可以同时启用一个模板。

5 . 最终下边员工用的就是启用的模板(尤其是这部门卡顿)

下面是电子合同的宏观泳道图:

三、页面介绍

1 . 合同模板管理页 2 . 新增模板页面 3 . 新建合同页面 4 . 合同填写页面

好了,基本的业务逻辑和页面就介绍这么多,特别卡顿的页面就是第四个页面,下面我们分析一下卡顿的原因。

四、卡顿分析

1 . 首先就是表单设计器的问题最严重,因为每一个组件需要很多配置项才能够支撑组件的渲染,而一个合同是由上千个组件组成,经过测试,一个合同模板需要5MB的存储空间(数据库用的是MongoDB,存储格式为字符串,几乎不影响),下面是一个输入框的配置

2 . 表单设计器的实现用了大量的闭包管理业务,我们都知道,闭包是特别耗内存的。

3 . 合同模板巨复杂,由上万个组件拼接而成,我把模板数据down下来看了一下,大约是16000多个组件,大小为3.4MB。

4 . 因为表单设计器中包括id,model,事件id都是前端随机生成的,采用随机字符串+时间戳的形式,一共46位。

5 . 合同项目属于大型项目,业务场景及其复杂,包括合同管理,附件管理,合同列表,新增页面,审批页面等等,我计算了一下,光路由页面就有三十多个,页面,组件,样式,业务巨多,如果不做处理,不卡才怪

五、性能优化

1. 第一次尝试

说一下我的优化思路:首先,电子合同由表单设计器和合同业务两个项目共同完成,合同模板加载慢的原因是浏览器渲染了大量的模板数据,这些模板数据是由多个组组成的(大约12个),我第一想到的就是分组渲染,先加载一个组,先让用户看到页面,然后在继续加载,一个一个,最终加载完成。这也是被大家认可的方案。

然后我就开始实现这个分组渲染,做了大概有二十多天吧,一点效果没出来。

先看一下渲染的代码:

<template v-show="itemManage==='group'">
  <preview-item-template v-for="(item) in domainNodeList"
                        :key="item.id"
                        :formNode="item"
                        :parent="domainNodeList">
  </preview-item-template>
</template>

上面就是所有组加载的代码,这是一个v-for,做分组渲染,我想到使用vue的异步组件实现,但是这是一个循环,所有的组件注册的都是同一个名字,这显然是不能用异步组件的,除非注册的是不同名字的组件,但是我想了很长时间都做出来效果,所以这二十多天,失败了。

2.第二次尝试

上边说了,模板加载慢是因为浏览器渲染了大量的数据,我们知道,js是单线程的,也就是说,所有任务只能在一个线程上完成,一次只能做一件事。前面的任务没做完,后面的任务只能等着。因此js处理数据的能力有限,所以在朋友的建议下调研了一把webworker

webworker的作用,就是为js创造多线程环境,允许主线程创建Worker线程,将一些任务分配给后者运行。在主线程运行的同时,Worker线程在后台运行,两者互不干扰。

看了一把文档我第一时间觉得这个方案不可行。说到底我们就是想要webworker为我们开辟线程用来处理大量数据,但是webworker处理的大数据,不是指数据量非常大,而是要从计算量来看,通常用时不能控制在毫秒级内的运算都可以考虑放在web worker中执行。而我们的合同模板数据恰恰是数据量大,并不需要做特别大的运算。

第二次尝试失败。

3.第三次尝试

后来在同事的建议下决定采用ssr,也就是服务端预渲染。我们平常写的vue项目打包后生成dist,运维会把这个文件夹放在服务器中,我们看到的页面其实就是生成执行的render函数,这是比较耗时的。

所谓的服务端渲染,就是在服务端生成静态页面,然后交给客户端渲染。

自己从零搭建一套服务端渲染的应用是相当复杂的,所以我最终选用了nuxt框架。关于nuxt框架我不多做介绍,可以自己去看文档(传送门)。这个框架有自己的脚手架,也是vue官方推荐的。

经过了一周的时间,完成了从vue向nuxt的迁移,大部门页面速度有了明显的提升。

除了我们想优化的新增合同页面。

经过分析,合同项目用到的组件库有element-UI和我问自己的表单设计器,element只有部门组件支持ssr,像是表格和树是不支持ssr的,所以就不存在服务端渲染了。

我也曾尝试过弄一把表单设计器,让它支持ssr,但是并没有效果,如果有谁知道,可以联系我。

很显然,第三次也失败了。

4.第四次尝试

命运总是很捉弄人,优化了一个多月的合同,速度并没有显著的提升,领导很着急,我也很着急。

突然有一天,我在回家的途中,记得那天风雨交加,雷霆大作,一声巨雷轰天响,把我好的idea都劈出来了。我一下子想到了分组加载的实现。

先来看一把代码的实现(只展示了部分代码):

<template>
  <div class="dialog-preview" v-show="!formLoading">
      <el-form  ref="previewForm" onsubmit="return false"
                :size="formSettingState.componentSize"
                @hook:mounted="formMounted"
                :model="formModels">

        <template v-show="itemManage==='group'">
          <preview-item-template v-for="(item) in cutDomainNodeList.one"
                                :key="item.id"
                                :formNode="item"
                                :parent="cutDomainNodeList.one">
          </preview-item-template>
        </template>
        <template v-if="itemManage==='group' && formLoadingTwo">
          <preview-item-template v-for="(item) in cutDomainNodeList.two"
                                :key="item.id"
                                :formNode="item"
                                :parent="cutDomainNodeList.two">
          </preview-item-template>
        </template>
         <template v-if="itemManage==='group' && formLoadingThree">
          <preview-item-template v-for="(item) in cutDomainNodeList.three"
                                :key="item.id"
                                :formNode="item"
                                :parent="cutDomainNodeList.three">
          </preview-item-template>
        </template>
        </template>
      </el-form>
  </div>
</template>
<script>
export default {
    data() {
        return {
          formLoading: true,
          formLoadingTwo: false,
          formLoadingThree: false
        }
    },
    computed: {
        cutDomainNodeList () {
          let { domainNodeList } = this;
          let length = domainNodeList.length;
          if ( length <= 4 ) {
            return {
              one: domainNodeList
            }
          }else {
            return {
              one: domainNodeList.filter((el, index) => index <=2 ),
              two: domainNodeList.filter((el, index) => index>2 && index <=5 ),
              three: domainNodeList.filter((el, index ) => index > 5)
            }
        }
    },
    methods: {
        formMounted () {
          setTimeout(() => { this.formLoading = false },  500);
          setTimeout(() => { this.formLoadingTwo = true },  700);
          setTimeout(() => { this.formLoadingThree = true},  900);
        }
    }
}

分块加载实现思路:

1 . 首先我把模板数据这个list利用计算属性先做了个判断,如果数组长度小于4,证明数据量较小,不需要分块加载,如果大于4证明数据量大,需要进行分块加载

2 . 分块加载是根据数组索引过滤的,第一块是0-2组,第二块是2-5组,第三块是索引大于5的(也可以分割的更细),然后再页面中分别遍历渲染

3 . 看一下html中的el-form这个标签,里边有个@hook:mounted="formMounted"这句话,@hook:+生命周期代表在这个生命周期时执行,我们等mounted执行完延时500mm开始加载第一块,700mm加载第二块,900毫秒加载第三块,这样分块加载的效果就出来了。

六、其他方面优化

首先添加了骨架屏组件,让用户在等待的时候能看到过渡效果。

上面提到,合同模板大约在3.4MB,这个就是个纯json,让浏览器一下子加载这个么大的数据难免卡顿,所以我就在想能不能优化一下模板大小,从而能够提升加载速度。

表单设计器中包括id,model,事件id都是前端随机生成的,采用随机字符串+时间戳的形式,一共46位,一个英文字符就是一个字节,这就是46个字节,所以我们可以缩短一下随机数的长度,从而减少一下模板大小。

最终选用了26位随机数,我算了一下,大约能减少一半大小。

后来我们让测试人员新生成了一个模板,果然,新模板大小1.44MB,缩短了一倍还多。

其他方面,我们知道表单设计器有些配置做的不到位,所以管理员不得不换个别的方式拖拽模板,所以我们加了一些配置项,从而使管理员可以少拖拽一些组件。这部分优化下来,模板大小大约减少了300多kb.

我们还可以优化一下表单设计器的代码,把闭包换个实现方式,应该也能提高加载速度,后续会做这些。

合同业务项目也优化了一些接口,代码,前后端交互方式,以及页面的交互方式提高了性能和视觉效果。

七、总结

这是我第一次费这么大劲做vue项目的性能优化,虽然坎坷,但也留下了好结果,我们从最初加载需要50秒甚至一分钟,到现在10秒左右就能加载成功,速度提高接近5倍。

今日成果,虽数月,但众人拾柴,得以燎原,此非一人之功,谢而不及。

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/CZhrUYLmUCn0Erxs-duAAQ

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 目录