跟踪Vue.js中的性能缺陷

发布于:2020-12-24 16:16:25

0

126

0

调试 Vue Netlify

作为一个游戏玩家,我的内心一直有一种做电子游戏的强烈欲望。几个月前,当我第一次参加Global Game Jam时,我就沉迷于这种冲动。我和我的团队使用Vue.js为web创建了一个名为“ZeroDaysLeft”的单页应用程序。这款游戏的主题是绿色,我们考虑了资本主义对地球环境的影响,并想在游戏中添加一些有益的信息。使用vuv .js制作的游戏并不多。我的团队晚了一天,在玩了一场石头剪刀布的游戏来选择我们的框架后,我们赶紧去编码它,并在周末结束时让我们的游戏运行起来。从本地来看,一切都很顺利。自然,我们为我们的代码弗兰肯斯坦感到自豪,并想与世界分享它。

只有一个问题,当我们构建应用程序和查询域时,它是如此占用内存。它几乎不能工作,我们试图运行它的每台机器都会在处理地狱中挂起——甚至我那健壮的基于Intel i7处理器的系统也会崩溃。game jam的时间限制将我们带回到现实中,我们决定将生产性能问题放在一边,这样我们至少可以在我们的设备上推出一款完整的游戏。就像几乎每一个“完成”的项目一样,我们第二天就忘记了。

只是我无法释怀。它一直困扰着我。Vue.js吗?Netlify吗?是我们的密码吗?我必须弄清楚。

调查经济放缓

我用Lighthouse做了一个快速的测试。幸运的是,Firefox有一个浏览器插件。这就是我得到的。

89%不坏。事实上,与许多广泛使用的网站相比,它是体面的。测试提到了一些潜在的问题,如速度索引和第一个内容和有意义的油漆。从理论上讲,解决这些问题可以提高分数,但不一定能改善应用程序巨大的性能问题。我们有两个图像和音频资产,但都不够大,不会导致挂起。我们可以过度优化这些已经优化过的资产,但这可能对我们没有任何帮助。

测试并没有为我们提供任何可能导致这种性能问题的真正见解。这时,我在想“是Vue吗?”“我没有理由这么想,但如果我不去核实,那就太愚蠢了。我检查控制台部署的站点,它是空白的。警告通常不会在生产环境中显示。当我在本地做同样的操作时,我被几个Vue警告击中了头部。

与大多数开发人员一样,我对控制台警告的理解是,它们只是警告而不是错误,因此我的注意力更好地集中在其他事情上。我一直希望消除这些警告可以修复我的生产问题。我决定再深入一点,然后修复它们。

所有这些警告都来自我创建的用于显示名为Cards的选项的组件。vue,因此该组件可能需要大量重写。

我决定按顺序处理这些控制台警告。

> [Vue warn]: Avoid using non-primitive value as key, use string/number value instead.
found in
---> <Cards> at src/components/Cards.vue

Vue.js有很多指令,使使用框架更加直观,例如v-for,它可以快速将数组呈现为列表。 使用它时,我们需要一个:key才能有效地重新渲染组件。 但是,我们使用对象作为键,这是非原始值,因此导致此错误。 我决定将index.description用作新键,因为它是一个字符串,并且只要值发生更改,就可以更有效地重新呈现。

> [Vue warn]: Duplicate keys detected: '[object Object]'. This may cause an update error.

found in
---> <Cards> at src/components/Cards.vue

将:key更改为字符串(index.description),以解决上一个错误,从而解决了重复的键错误。 我们只能将字符串类型写入DOM,因此,当我们传递要渲染的对象时,该对象将转换为等效的字符串(即[object Object]),并且因为这以前是我们的键,所以每个对象尽管拥有不同的值 ,将转换为[object Object],因此出现重复的键警告。 既然钥匙不是物体,警告就会消失。 所以要提高效率。

> [Vue warn]: You may have an infinite update loop in a component render function.
found in
---> <Cards> at src/components/Cards.vue


对于一个非常模糊的警告,此警告似乎是最重要的。 无限循环是内存消耗的代名词。 该消息并未告诉我们可能出了什么问题。 它确实暗示它与组件中的render函数有关。 也许是因为我们的骇客代码,我们触发了不间断的更新,而这占用了太多的计算能力,从而导致浏览器和设备崩溃。

该警告至少告诉我们要检查Cards.vue,所以我的第一个想法是检查组件中的反应性,因为这可能会导致错误。 反应性属性在更改后会触发重新渲染。

我们正在显示index.days和index.description中的数据。 但是,我们不会更改此数据。 我们从cardInfo数组获得索引。

> v-for="index in cardInfo.sort(() => Math.random() - 0.7).slice(0,4)"

我们使用此代码块对数组中的元素进行随机排序,然后将前四个元素显示为玩家选择的选项。当用户单击一个选项时,将调用effects()函数,除了计算动作如何影响游戏状态之外,它还使用cardInfo上的拼接原型删除前四个元素。

在使用虚拟DOM的Vue这样的框架中,随着诸如cardInfo之类的反应性属性一起使用,每当数据属性的值更改时,都会触发重新渲染。在本例中,我们将直接使用sort()原型对其进行更改,然后删除元素以仅对其进行重新排序。所有这些都会触发“无限”重新渲染,从而引发警告。

我决定更改如何过滤数据的逻辑,并停止对反应性属性cardInfo进行多次更改。我安装了lodash.shuffle并定义了一个计算属性shuffledList(),它将创建一个名为list的cardInfo副本。我对其应用了随机播放操作,并返回了“冻结”结果,该结果将被切片以显示四张卡片。我们使用了Object.freeze(),它将使我们返回的对象不可变,从而完全停止了所有重新渲染。问题解决了。

被我的框架绊倒

老实说,当我开始调查时,我认为我必须优化很多资产。 它只是说明了在使用许多框架抽象时我们必须非常小心—特别是在Vue中,必须正确且仅在必要时才使用每个指令,因为它们绝对有折衷。

这让我想到了我在做什么,这可能会给我的应用程序增加不必要的性能问题。 大多数现代的前端框架都进行了很多抽象,使我们更容易地为Web制作应用程序。记住使用这些东西可能会引起的潜在性能问题很重要。 我经常使用Vue.js,并决定探索一些我使用的指令,甚至不考虑它们可能对我的应用程序带来的性能影响。 特别是三个非常流行的指令对我来说很突出。

  • v-if and v-show

这两个指令都用于有条件地渲染元素,但是它们在幕后的工作方式却大不相同,因此,因此必须使用不同的方式。 v-if最初不渲染组件,仅在条件为真时才渲染组件。 这意味着,如果您多次切换组件的可见性,它将被重复重新渲染。 如果您要多次更改组件的可见性,则不想使用此功能。 这会影响您的表现。

v-show是一个很好的选择。 无论使用CSS如何,这都会呈现您的组件,但是只会根据条件是true还是false使其可见。 这种方法确实有其缺点,因为它不会将非必要组件的渲染推迟到实际需要它们出现在屏幕上的时候。 如果您的初始渲染不太沉重,则效果很好。

  • v-for

此伪指令通常用于从数组中呈现列表。它具有item in list形式的特殊语法,其中list是源数据数组,而item是要迭代的数组元素的别名。默认情况下,Vue在源数据阵列上添加监视程序,每当发生更改时,该监视程序就会触发重新渲染。持续不断的重新渲染会对应用程序性能产生不利影响。考虑实用程序很重要,如果您只想可视化对象,则Object.freeze()是一个很好的解决方案,可以大大提高性能。但是请务必记住,您将无法更新组件或编辑对象数据。

这样做并意识到Lighthouse可能会检查以更直接的方式查看可能影响用户体验的应用程序性能,我被问到如何跟踪服务器上的应用程序性能。我们是否让直觉和开发人员知道自己在做什么以及正在使用最佳实践的假设?无论如何,这种整体经验使我对单页应用程序性能有不同的看法。随时在GitHub上查看项目存储库,或在Twitter上对我问好。