前言
代码分割是提升单页应用初始加载速度的重要方式之一。因为用户不用在第一次进入应用时下载所有代码,用户能更快的看到页面并与之交互。这会改善用户体验,尤其在移动端;而且这对 SEO 有很大帮助,因为 Google 会降低加载速度慢的网站权重。
上周我写了一篇关于Vue.js 与 Webpack 如何分割代码的文章,长话短说,每个组件都封装在单个文件中,那很容易分割代码,当你导入模块时,Webpack 可以创建一个分割点,并且 Vue 也可以很方便的加载一个异步组件。
我认为代码分割最困难的部分不是如何让它工作起来,而是何时、何地让它工作。我想说,当设计你的应用时,就要将代码分割作为架构考虑进去。
在这篇文章中,我将介绍目前 Vue.js 的三种代码分割方式:
By page(按照页面切分)
By page fold(按照页面的可见区域折叠切分)
By condition(按条件加载)
注:这篇文章最初于2017/07/08发表在Vue.js开发博客上。
1.By page(按照页面切分)
按照页面切分是思路最清晰的。这个简单的应用有三个页面:
我们假设每个组件都是一个单独的文件,比如:Home.vue
, About.vue
和 Contact.vue
,然后我们可以使用 Webpack 的动态 import
(dynamic import) 功能拆分成单独的构建文件。当用户访问不同页面时,Wenpack 会异步加载并请求改页文件。
如果你使用 vue-router
,这很容易实现,因为你的页面已经在单独的组件里了。
|
|
看看我们编译代码时的统计数据,每个页面都在它们自己的文件里,但要注意到有个重要的bundle文件叫 build_main.js,它包含了所有的公共代码以及异步加载其他文件的逻辑。无论用户访问哪个路由,都必须先加载它。
现在我访问 http://localhost:8080/#/contact
加载 Contact 页面,我查看 Network 菜单,发现下列文件被加载:
注意 build_main.js 这一栏的 initiator 值为 (index)。这意味着 index.html 请求了这个脚本,这正是我们所期盼的。但是 build_1.js 的 initiator 却是 bootstrap_a877…,这是 Webpack 脚本负责的异步加载文件。当你使用 Webpack 的动态导入功能,这个脚本会自动加入构建。最重要的一点是: build_1.js 不会阻塞初始页面的加载。
2.By page fold(按照页面的可见区域折叠切分)
折叠以下(Below the “fold”)代表页面初始时不可见的部分。你可以异步加载这些内容,因为用户通常需要一两秒钟才能阅读完折叠以上的内容,尤其是在第一次访问站点时。
在这个实例应用中,我考虑把折叠线设在刊头下。那么让我们在页面初始化时加载导航栏和刊头,它们之下的所有内容,稍后再加载。我会创建一个名叫 BelowFold 的组件,提取出相关的代码如下:
Home.vue:
|
|
BelowFold.vue:
|
|
当我们编译代码时,可以看到 below-fold 被打包成了单独的文件:
提示:below-fold 小到只有1.36k,看起来似乎不值得把它单独分离出来。因为现在只是一个很小的演示应用。在真实的应用中,页面的大部分内容都在折叠以下,因此可能有大量的代码,它包括 JS、CSS 以及所有子组件。
3.By condition(按条件加载)
另一个选择方案是按条件加载。比如:模态框、Tab页、菜单等。
这个应用有个模态框,当你按下”Sign up today”按钮时会弹出它:
和之前一样,我们只是将模态框代码移动到它自己的单个文件组件中:
Home.vue:
|
|
HomeModal.vue:
|
|
注意我在模态框上加了 v-if
。布尔值 show
用来开启/关闭模态框,并且它也用来判断是否渲染模态框本身。因为初始化页面时 show
为 false
,只有当模态框打开时,才会下载代码。
这很合适,因为如果用户没有打开模态框,那这块代码是不会下载的。唯一的缺点是:它有很小的用户体验成本,当用户按下按钮后必须等待文件下载完成。
再次编译,下面是现在的输出结果:
啊哈,我们又节省了5KB的首屏流量…
结论
除了以上三种代码分割的方法,我相信一定还有其他方法去实现,只要你运用自己的想象力!
本文译者:余震(Freak)
译文出处:Rockjins Blog
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN许可协议。转载请注明出处!