最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 纯前端生成海报实践及其性能调优

    正文概述 掘金(腾讯IMWeb团队)   2021-05-29   613

    1 需求背景

    接到了一个紧急需求,需要根据 Excel 表格中学生的信息以及考试成绩生成相应的海报。

    Excel 数据和需要生成的海报的样式如下:

    纯前端生成海报实践及其性能调优

    纯前端生成海报实践及其性能调优

    由于需求紧急,没有时间拉上后端同学,所以 Excel 表格的数据解析和海报生成功能都需要由前端开发。

    以下几个技术点需要关注:

    1. Excel 可以通过 sheetjs 来处理,通过在 XLSX.utils.sheet_to_json 将 Excel 中的数据转化为 JSON 格式数据。
    2. 海报图片的生成可以先通过 html2canvas 将 HTML 转化成 canvas ,然后通过 canvas.toBlob 获得。
    3. 最终通过 JSZip 将图片打包进压缩包中。
    4. 这里表单可配置项会比较多,因此我们需要一个配置导入导出功能,这里我们可以使用 FileReader 来实现表单配置导入,FileReader.readAsTextapi 能够读取文本的内容,更多用法可以参考 MDN FileReader。

    在此基础上,确定此需求的总体开发思路:

    1. 首先我们需要一个表单,获得海报可变文案的配置信息,例如不同题目考试成绩所对应的评语。
    2. 遍历 Excel 中的每一条数据,根据每一条数据和表单的配置信息生成对应海报的 HTML 模板。
    3. 根据 HTML 模板生成图片,并将图片数据保存进压缩包的对象中。
    4. Excel 中的数据处理完后,下载压缩包,结束流程。

    按照这个流程将功能开发完毕后,我在自己的机器上使用100条数据量的 Excel 表格进行测试,可以成功生成对应的压缩包,压缩包中的图片也没有问题,给运营同学演示后,她也表示很满意。

    2 测试问题

    但是当天晚上运营同学在自己的电脑测试这个工具时,悲剧发生了……

    纯前端生成海报实践及其性能调优

    在运营同学的电脑上,使用 15 条 Excel 表格数据生成海报时表现正常,当增加到 20 条 Excel 表格数据时,出现了网页崩溃的情况,提示 Out Of Memory。

    3 分析问题

    3.1 js内存问题

    现在让我们来一起分析一下,是在哪里出现了问题?

    第一波分析发现,最有可能出现问题地方就是步骤 3——最终通过 JSZip 将图片打包进压缩包中。

    这里压缩包对象所占用的内存在 Excel 表格数据处理完成并下载之前是不会被释放的,会一直增长。

    所以我们有了一个简单的方案——分包。每处理 10 条数据就下载一次压缩包,将 JSZip (压缩包对象)所占用的内存释放。

    但是事情真的有这么简单吗?20 张图片的数据以每张 1MB 的大小计算也才 20MB,怎么可能会导致网页崩溃呢?

    凭空猜测没什么作用,首先我们使用浏览器的 Performance 工具进行分析

    纯前端生成海报实践及其性能调优

    可以看到 JS Heap 在每处理一条 Excel 表格数据后都会增长,没有得到释放,但是这里没有得到释放的内存占用真的是 JSZip 导致的吗?

    继续使用浏览器的 Memory 工具进行分析

    纯前端生成海报实践及其性能调优

    可以看到,内存占用确实是一直在涨,没有得到释放,放大其中的一项。

    纯前端生成海报实践及其性能调优

    什么?竟然是 system.context ?作为一个前端开发,相信你看到这个词脑子里第一个冒出的念头应该就是上下文。检查代码,发现代码中使用了递归,所以造成了大量内存的使用,这里就不展示问题代码了。

    将代码修改为循环语句后,再进行测试。

    纯前端生成海报实践及其性能调优

    可以看到内存的增长已经正常。可以让运营同学再次进行测试。

    3.2 DOM 问题

    问题就这样被解决了吗?

    信心满满的找到运营同学进行测试,结果出乎意料,运营同学的电脑依然处理不了 40 条以上的 Excel 表格数据,而且在测试中还出现了一个问题,数据处理到某个阶段时,会卡住很久!

    事情变得奇怪起来,我们继续进行分析。

    造成内存溢出的原因一般有两点,JS 和 DOM。既然 JS 的问题我们已经解决,那我们就看看 DOM。

    我们的整体流程中,对 DOM 进行操作的地方有两点:

    1. 根据 Excel 表格数据生成对应海报的 HTML 模板。
    2. 根据 HTML 模板生成图片。

    第一点应该不存在内存溢出问题,因为我们既没有在 HTML 模版上添加事件,在处理下一条数据时也是直接覆盖上一次生成的HTML 模板,不会导致 DOM 节点不停增加。

    继续分析第二点,我使用了第三方库 html2canvas ,由对应的节点生成 canvas 对象,之后由 canvas 对象生成图片的二进制数据。

    根据 html2canvas 文档的指引,我设置 removeContainer 属性保留其生成 canvas 对象时所克隆的 DOM 元素并查看

    纯前端生成海报实践及其性能调优

    结果出乎意料,html2canvas 完整的克隆了我们的 DOM 结构,除目标节点外还克隆了 React 的根结点,script 标签,link 标签。

    此时,数据处理慢以及在处理某条数据时卡住的问题就清楚了,由于 html2canvas 完整的克隆了我们的 DOM 结构,不仅复制了很多没用的节点,同时由于克隆了 script 标签,link 标签,还会发起网络请求下载相关的资源。

    我们需要把进行操作的节点插入在 body 标签下,根据文档指引,可以使用 html2canvas 提供的ignoreElements属性解决以上问题:

    const canvas = await html2canvas(root, {
      imageTimeout: 10000,
      ignoreElements: (ele) => ele.id === 'root' || ele.tagName.toUpperCase() === 'IFRAME' || ele.tagName.toUpperCase() === 'SCRIPT' || ele.tagName.toUpperCase() === 'LINK',
    });
    

    通过以上代码,我们将无用的节点和会造成网络请求的标签进行了过滤。

    优化过后,再让运营同学进行测试,这时处理一千条数据的 Excel 表格数据也不会再出现网页崩溃的问题了,同时处理速度也大大提升,1000 条数据在 4 分钟内可以处理完毕。

    4 小结

    回到最开始,JSZip 占用的问题依然存在,我们依然需要进行分包,不过分包的大小可以提升到1000条数据。

    但是我们可以看到,如果不能找到问题的根本所在,一开始就进行分包也无济于事。

    网页显示“喔唷,崩溃啦!”怎么办?请别着急,仔细分析才能解决问题。

    纯前端生成海报实践及其性能调优


    起源地下载网 » 纯前端生成海报实践及其性能调优

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元