Vue.js应用性能优化:第二部分---路由懒加载和 Vendor bundle 反模式

前一篇文章中,咱们学习了什么是代码分割,它是如何与 Webpack 一块儿工做的,以及如何在Vue应用程序中使用延迟加载。如今,咱们将更深刻地研究,并学习用于分割 Vue.js 应用程序最实用的模式。javascript

本系列文章基于对 Vue Storefront 性能优化过程的学习。经过使用下面的技术,咱们可以将初始文件的大小减小70%,并在眨眼间使其加载。前端

应用程序增加的问题

Vue-router 是一个库,它容许将咱们的web应用程序天然地分割成单独的页面。每一个页面都是与某个特定URL路径相关联的路由。vue

了解了这一点,假设咱们有一个简单的应用程序,其结构以下:java

1-2.jpg
整个JS代码打包在一个文件中 -  app.jsnode

你可能已经注意到,咱们正在访问的路径,可能不须要 Home.vueAbout.vue(和它依赖的lodash),但它们都在相同的 app.js 文件中,不管用户访问哪个路径,都会被下载。多么浪费下载和解析时间啊!react

若是咱们下载一个额外的路由,这并非什么大不了的事,但你能够想象这个应用会变得愈来愈大,任何新的增长将意味着在首次访问时要下载更大的文件。webpack

仅仅一秒钟的时间足以让用户心理发生变化,并颇有潜在可能会离开咱们的网站,这是不能接受的。git

image.png

来自 Ilya Grigorik 关于性能和人类感知的精彩演讲github

以上图片中出现的英文译文:web

  • Wetware perception reaction times 人脑感知反应时间
  • instant 马上
  • slight perceptible delay 轻微可察觉的延迟
  • Task focus,perceptible delay 明显的延迟
  • Mental context switch 心理发生变化
  • I'll come back later 我一下子再来

基于路由的代码分割

为了不让应用程序变得更糟,咱们只须要使用上一篇文章中学习的动态导入语法为每一个路由建立单独的包

像在 Vue.js 中很容易实现延迟加载组件同样,咱们要作的不是直接将组件导入到路由对象中,而是传递一个 动态导入函数,只有在访问这个路由时,才会下载对应的路由组件。

因此不要像这样静态导入路由组件:

import RouteComponent form './RouteComponent.vue'
const routes = [{ path: /foo', component: RouteComponent }]

咱们须要动态导入它,这将建立一个新的包,并将此路由做为入口点:

const routes = [
  { path: /foo', component: () => import('./RouteComponent.vue') }
]

知道了这些,让咱们看看动态导入后打包的文件和路由是什么样子的:

4-5.jpg

使用这个设置,webpack 将建立三个包:

  • app.js 咱们的主文件,包含了应用程序入口点(main.js)和每一个路由所须要的库/组件。
  • home.js/** 路径时才被下载。
  • about.js/about** 路径时才会被下载。

_为了便于理解,文件名称并非由webpack生成的真实名称。其实是根据webpack配置生成 0.js1.js** 等_,具体取决于您的webpack配置。

这种技术几乎适用于全部的应用,而且能够产生很是好的效果。

在许多状况下,基于路由的代码分割将解决全部的性能问题,而且能够在不到几分钟的时间内应用到几乎任何应用程序中!

Vue生态系统中的代码拆分

你可能正在使用 Nuxtvue-cli 来建立你的应用程序。若是是这样,重要的是要知道它们都有关于代码拆分的一些自定义行为:

  • vue-cli3prefetchingvue-cliprefetching** 的知识,请看这篇文章
  • Nuxt路由系统,全部页面路由的代码分割都是开箱即用的。

如今让咱们来看看很是流行且常被用到的反模式(anti-pattern),它能够下降基于路由的代码分割的影响。

Vendor bundle 反模式

Vendor bundle 一般用于包含 node_modules 中的全部模块的单独js文件。

虽然把全部文件都打包在一块儿,以便将全部依赖关系保存在一个地方并缓存它们可能很吸引人,但这种方法引入了咱们将全部路由打包在一块儿时遇到的一样的问题:

6.png

你看到问题了吗?即便咱们只须要在一个路由中使用 lodash(它是其中一个依赖项),它就会被打包在 vendor.js 中以及全部其余依赖项中,所以它始终将会被下载。

将全部依赖项打包在一个文件中听起来很吸引人,但这会延长应用程序的加载时间。咱们能够作得更好!

咱们的应用程序使用基于路由的代码分割,就足以确保只下载所须要的代码。但这会致使一些代码重复。

假设 Home.vue 也须要 lodash

7.png

在这种状况下,从 /about (about .vue) 跳转到 / (Home.vue) 将会下载 lodash 两次。

虽然仍然比下载大量冗余代码要好,可是若是咱们已经知道了有这种依赖关系,那么作不到被重用就没有意义,对吧?

这就是 webpack splitChunksPlugin 能够帮助咱们的地方。只要在 webpack 的配置中添加下面这几行代码,咱们就能够将公共依赖项分组到一个单独的文件中,这样就能够被共享了。

// webpack.config.js
optimization: {
  splitChunks: {
    chunks: 'all'
  }
}

chunk 属性中,咱们只是告诉 webpack 应该优化那些代码块。正如您可能已经猜到的那样,将该属性设置为 all 意味着它应该优化全部依赖项。

您能够在 webpack文档 中阅读关于此过程的更多信息。

总结

按路由拆分代码是保持初始加载文件大小较小的最佳(也是最简单)方法之一。接下来,咱们将学习其余部分(Vuex和单独的组件)也可以从主文件分割出来并延迟加载。

若是对你有帮助,请关注【前端技能解锁】:
qrcode_for_gh_d0af9f92df46_258.jpg

相关文章
相关标签/搜索