虽然现在网络环境和电子设备变得越来越好,但是保持应用程序快速加载变得越来越困难。在本系列中,我将深入研究我们在实践中使用的Vue性能优化技术,并且您可以在Vue.js应用程序中使用它们,使应用程序快速加载并顺利执行。我的目标是让这个系列成为关于Vue应用程序性能的全面而完整的指南。
系列文章:
Vue.js应用性能优化二
Vue.js应用性能优化三
请关注微信公众号和头条号,「前端知否」
Webpack bundling 打包机制
本系列中的大多数技巧都将集中在如何使我们的JS包更小。要了解它,首先我们需要了解Webpack如何打包所有文件。
打包我们的资源(assets)时,Webpack会创建一个依赖图。它是一个基于导入链接所有文件的图表。假设我们在webpack配置中指定了一个名为main.js的文件作为入口点,它将成为我们依赖图的根。现在,我们将在此文件中导入的每个js模块将成为图中的节点,并且在这些节点中导入的每个模块都将成为其节点。
Webpack使用此依赖关系图来检测它应该包含在输出包中的文件。输出包只是一个(或我们将在后面的部分中看到的多个)javascript文件,其中包含依赖图中的所有模块。
这个bundle包本质上是我们整个应用程序的JavaScript。
我们可以用下图来说明这个过程:
现在我们知道webpack是如何打包的,很明显我们的项目越大,初始JavaScript包就越大。
越大的初始bundle,下载和解析,我们的用户所需的时间就越长。用户必须等待的时间越长,他离开我们网站的可能性就越大。事实上,据搜索引擎统计,53%的移动用户留下的页面加载时间超过3秒。
总而言之,更大的bundle=更少的用户,这可以直接转化为潜在收入的损失。有关案例统计,延迟2秒导致每位访客的收入损失4.3%。
延迟加载
那么当我们仍然需要添加新功能并改进我们的应用程序时,我们如何削减budle包大小?答案很简单 - 延迟加载和代码分割。
顾名思义,延迟加载是一个懒惰地加载应用程序的部分(块)的过程。换句话说 - 只有在我们真正需要它们时加载它们。代码拆分只是将应用程序拆分为多个延迟加载的代码块的一种处理方式。
在大多数情况下,当用户访问您的网站时,您不需要立即使用Javascript包中的所有代码。
例如,我们不需要花费宝贵的资源来为首次访问我们网站的访客加载“我的页面”区域。或者可能存在每个页面上不需要的模态,工具提示和其他零件和组件。
当只需要几个部分时,在每个页面加载时下载,解析和执行整个包的所有内容都是浪费。
延迟加载允许我们拆分捆绑包并仅提供所需的部分,这样用户就不会浪费时间下载和解析不会使用的代码。
要查看我们网站中实际使用了多少JavaScript代码,我们可以转到devtools - > cmd(ctrl) + shift + p - >输入coverage - >点击Performance instrument coverage 。现在我们应该能够看到实际使用了多少下载的代码。
标记为红色的所有内容都是当前路由上不需要的东西,可以延迟加载。如果您正在使用source maps,则可以单击此列表中的任何文件,并查看那些未调用部分。正如我们所看到的,甚至vuejs.org还有很大的改进空间)。
通过延迟加载适当的组件和库,我们设法将Vue Storefront的捆绑大小减少了60%!这可能是获得性能提升的最简单方法。
现在我们知道延迟加载是什么,它非常有用。现在是时候看看我们如何在我们自己的Vue.js应用程序中使用延迟加载。
动态导入
我们可以使用webpack的动态导入,轻松地加载我们应用程序的某些部分。让我们看看它们的工作原理,以及它们与常规导出模块的区别。
如果我们以这样的标准方式导入JavaScript模块:
它将作为main.js的节点添加到依赖关系图中并与之捆绑在一起。
但是,如果我们仅在某些情况下需要我们的Cat模块,例如对用户交互的响应,该怎么办?将此模块与我们的初始bundle包捆绑在一起是一个坏主意,因为它不是一直需要的。我们需要一种方法告诉我们的应用程序什么时候应该下载这段代码。
这是动态导入可以帮助我们的地方!现在看一下这个例子:
我们来看看这里发生的事情:
我们创建了一个返回import()函数的函数,而不是直接导入Cat模块。现在,webpack会将动态导入的模块的内容捆绑到一个单独的文件中。表示动态导入模块的函数返回一个Promise,它将使我们在Promise resolve后,可以访问导出的模块成员。
然后,我们可以在需要时下载此可选块。例如,作为对某个用户交互的响应(如路由更改或单击)。
通过动态导入,我们基本上将给定节点(在这种情况下为Cat)隔离,当我们决定需要时,它将被添加到依赖图并下载此部分(这意味着我们也砍掉了一些Cat.js 中导入的模块)。
让我们看另一个更好地说明这种机制的例子。
假设我们有一个非常小的网上商店,有4个文件:
- main.js 作为我们的主要bundle包
- product.js 用于产品页面中的脚本
- productGallery.js 用于产品页面中的产品库
- category.js 用于类别页面中的脚本
在上面的代码中,根据当前路由,我们动态导入产品或类别模块,然后运行由它们两者导出的init函数。
了解动态导入的工作方式之后,我们知道产品和类别最终会以单独的bundle包形式出现,但是未动态导入的productGallery模块会发生什么?正如我们所知,通过动态导入模块,我们削减了依赖图中的一部分。此部件中导入的所有内容都将捆绑在一起,因此productGallery将与产品模块位于同一个bundle包中。
换句话说,我们只是为依赖图创建某种新的入口点。
延迟加载Vue components
现在我们知道延迟加载是什么,以及为什么需要它。现在是时候看看我们如何在Vue应用程序中使用它了。
好消息是它非常简单,我们可以懒加载整个vue单一文件组件(SFC),vue文件语法和HTML, CSS一样。不熟悉的话,去看看官方文档。
现在只有在请求时才会下载组件。以下是调用Vue组件动态加载的最常用方法:
- 调用包含导入的函数
- 渲染组件
请注意,仅当请求的组件在模板中渲染时,才会调用lazyComponent函数。例如这段代码:
在DOM中需要渲染组件之前,组件将不会加载。想要加载,只要v-if值更改为true即可。
总结
延迟加载,是使您的Web应用程序更高效并减少js bundle大小的最佳方法之一。我们已经学习了如何使用Vue组件进行延迟加载。
在本系列的下一部分中,我将向您展示在任何Vue.js应用程序上获得显着性能提升的最有用(也是最快)的方法。
您将学习如何使用异步路由拆分Vue代码,以及此过程中推荐的最佳实践。