内心对游戏有着深深的热爱,一直渴望自己制作一些电子游戏。几个月前,我开始让这个梦想成为现实,并第一次参加了GlobalGameJam。我和我的团队使用Vue.js构建了一个名为“ZeroDaysLeft”的游戏:https://zerodaysleft.netlify.com/以Web上的单页应用程序的形式。这个游戏的主题是环保。考虑到商业活动对地球环境的影响,我们希望就此话题进行一些有益的讨论。使用Vue.js制作的游戏并不多。我的团队迟到了一天,并选择了我们要在猜谜游戏中使用的框架;我们快速完成代码,并在周末结束时获得了游戏的工作版本。在本地测试时一切正常。自然地,我们为我们编写的第一款游戏感到自豪,并希望与全世界分享它。但是有一个问题——当我们构建应用程序并开始查询域时,内存使用量激增。它几乎无法运行,在任何机器上都会死机,甚至在强大的基于英特尔i7处理器的系统上也会崩溃。游戏大赛的时间限制让我们回到了现实,我们决定将生产性能放在一边,这样我们至少可以制作一款可以在我们自己的设备上运行的完整游戏。像大多数“完成”的项目一样,我们第二天就把它抛在脑后。但是我放不下自己。它一直困扰着我。Vue.js有问题吗?是Netlify吗?还是因为我们的hacky代码?我必须找出答案。为了调查性能缓慢的原因,我首先使用Lighthouse进行了快速测试。幸运的是,Firefox为此提供了一个浏览器插件:https://addons.mozilla.org/en-US/firefox/addon/google-lighthouse/下面是我得到的。89%是一个相当不错的数字。事实上,与许多流行的网站相比,这个网站的表现相当不错。该测试指出了一些潜在的问题,例如速度指标和第一个有意义的内容绘制步骤。理论上,解决这些问题会进一步提高分数,但不一定能解决应用程序面临的严重性能问题。我们的游戏中有一些图形和音频资产,但都不足以让游戏停在那里。我们也可以过度优化这些已经优化过的资源,但这可能根本无济于事。此测试不允许我们真正找出可能导致此性能问题的原因。于是我开始思考:“会不会是Vue的问题?”没有理由出现这种情况,但你不检查是愚蠢的。我检查了已部署站点的控制台,它是空白的。但是警告往往不会出现在生产中。当我在本地做同样的事情时,我被一堆Vue警告吓了一跳。像大多数开发人员一样,我不太注意控制台警告,将它们视为警告,而不是错误;所以我通常把注意力集中在别处。也许删除这些警告可以解决我的生产问题,我决定深入研究每一个并修复它们。所有这些警告都来自我创建的用于显示名为Cards.vue的选项的组件,因此该组件可能需要大量重写。我决定按顺序处理这些控制台警告。>[Vuewarn]:Avoidusingnon-primitivevalueaskey,usestring/numbervalueinstead.foundin--->atsrc/components/Cards.vue.vue.js有很多指令可以让我们更直观的使用框架,例如v-for快速将数组呈现为列表。使用它时,我们需要一个:key来有效地重新渲染组件。但是我们使用了一个对象作为键,它是非原始值,因此导致了这个错误。我决定使用index.description作为新键,因为它是一个字符串,并且当值更改时它会更好地重新呈现。>[Vuewarn]:Duplicatekeysdetected:'[objectObject]'.Thismaycauseanupdateerror.foundin--->atsrc/components/Cards.vue会把key改成字符串(index.description)来解决前面的错误,只是可以解决这个重复键错误。我们只能将字符串类型写入DOM,因此当我们将对象传递给渲染时,该对象将转换为等效的字符串(即[objectObject]);并且由于这曾经是我们的键,所以Each对象会被转换为[objectObject](除非对象有不同的值),然后就会出现duplicatekeywarning。现在键不是对象,警告消失了,效率提高了。>[Vuewarn]:Youmayhaveainfiniteupdateloopinacomponentrenderfunction.foundin--->atsrc/components/Cards.vue中一个非常模糊的警告,这个警告似乎是最重要的:无限循环意味着内存消耗。该消息没有告诉我们可能出了什么问题,但它确实暗示问题出在组件中的渲染函数上。也许是因为我们编写的代码很棘手,会触发不间断更新并占用大量计算能力,导致浏览器和设备崩溃。这个警告至少告诉我们检查Cards.vue,所以我的第一个想法是检查组件中的reactprops,因为这可能会导致错误。React属性在更改时会触发重新渲染。我们正在显示来自index.days和index.description的数据。但是我们不更改这些数据,我们从cardInfo数组中获取索引。>v-for="indexincardInfo.sort(()=>Math.random()-0.7).slice(0,4)"我们用这段代码对数组中的元素进行随机排序,然后把前四个元素显示为播放器选择的选项。effects()函数在用户点击一个选项时被调用,除了计算一个动作如何影响游戏状态之外,还会使用cardInfo上的拼接原型删除前四个元素。在像Vue这样使用虚拟DOM的框架中,具有像cardInfo这样的响应式属性,只要数据属性的值发生变化,就会触发重新渲染。在我们的应用程序中,我们将直接使用sort()原型对其进行更改,然后删除元素以重新排序。所有这些都会触发“无限”重新渲染,从而引发警告。我决定更改数据过滤的逻辑并停止对反应属性cardInfo进行多次更改。我安装了lodash.shuffle并定义了一个计算属性shuffledList(),它将创建一个cardInfo命名列表的副本。我对它应用了一个随机排序操作,它返回了一个“冻结”的结果,然后将其拆分为显示四张牌。我们使用Object.freeze()这将使我们返回的对象不可变,完全停止所有重新渲染。至此,问题就解决了。掉进框架的坑说实话,刚开始调查性能下降的原因时,我觉得必须优化很多资源才能解决问题。最后这个结果说明,我们在使用很多框架抽象的时候一定要非常小心——尤其是在Vue中,只在必要的时候使用某条指令,而且用法一定不能错,因为它们肯定有自己的价格。这也让我想到了我做过的其他工作,在这些工作中,应用程序可能会因为框架而出现不必要的性能问题。大多数现代前端框架都有很多抽象,可以更轻松地为Web开发应用程序。但是我们应该记住,使用这些东西可能会导致潜在的性能问题。我经常使用Vue.js,所以我决定探索一些我过去使用过的指令,甚至没有考虑它们可能对应用程序产生的性能影响。三个最流行的命令引起了我的注意。1、v-if和v-show指令都是用来有条件地渲染元素的,但是它们背后的工作机制有很大的不同,所以用法也有很大的不同。v-if最初不渲染组件,但仅在条件为真时才渲染组件。这意味着当您多次切换组件的可见性时,它会不断地重新渲染。如果您要多次更改组件的可见性,请不要使用此功能。这会影响你的表现。v-show是一个很好的替代品。无论您是否启用CSS,您的组件都会被渲染,但只会根据条件是真还是假才可见。这种方法确实有其缺点,因为它不会延迟非必要组件的渲染,直到您需要它们实际出现在屏幕上。如果您的初始渲染没有那么复杂,那很好。2.v-for该指令通常用于从数组中渲染列表。它具有列表中表单项目的特殊语法,其中列表是源数据数组,项目是要迭代的数组元素的别名。默认情况下,Vue在源数据数组上添加观察者,只要有变化就会触发重新渲染。这种持续的重新渲染会对应用程序性能产生不利影响。如果你只是想可视化对象,那么Object.freeze()是一个很好的解决方案,可以大大提高性能。但请务必记住,您将无法更新组件或编辑对象数据。在这项研究中,我还意识到Lighthouse可能正在以更直接的方式检查影响用户体验的应用程序性能指标,因此我的下一个问题是如何跟踪服务器上的应用程序性能。我们是否过于依赖直觉,假设开发人员知道他们在做什么,假设他们遵循最佳实践?无论哪种方式,这种经历都让我对单页应用程序的性能有了不同的看法。您可以在GitHub上查看上述项目的存储库:https://github.com/Maria218/GlobalGameJamThing