代码分割是提高单页应用初始加载速度的重要方式之一。由于用户不用在第一次进入应用时下载全部代码,用户能更快的看到页面并与之交互。这会改善用户体验,尤为在移动端;并且这对 SEO 有很大帮助,由于 Google 会下降加载速度慢的网站权重。vue
上周我写了一篇关于Vue.js 与 Webpack 如何分割代码的文章,长话短说,每一个组件都封装在单个文件中,那很容易分割代码,当你导入模块时,Webpack 能够建立一个分割点,而且 Vue 也能够很方便的加载一个异步组件。webpack
我认为代码分割最困难的部分不是如何让它工做起来,而是什么时候、何地让它工做。我想说,当设计你的应用时,就要将代码分割做为架构考虑进去。web
在这篇文章中,我将介绍目前 Vue.js 的三种代码分割方式:vue-router
By page(按照页面切分)bootstrap
By page fold(按照页面的可见区域折叠切分)
sxsa架构
注:这篇文章最初于2017/07/08发表在Vue.js开发博客上。异步
按照页面切分是思路最清晰的。这个简单的应用有三个页面:网站
咱们假设每一个组件都是一个单独的文件,好比:Home.vue
, About.vue
和 Contact.vue
,而后咱们可使用 Webpack 的动态 import
(dynamic import) 功能拆分红单独的构建文件。当用户访问不一样页面时,Wenpack 会异步加载并请求改页文件。ui
若是你使用 vue-router
,这很容易实现,由于你的页面已经在单独的组件里了。
const Home = () => import(/* webpackChunkName: "home" */ './Home.vue');
const About = () => import(/* webpackChunkName: "about" */ './About.vue');
const Contact = () => import(/* webpackChunkName: "contact" */ './Contact.vue');
const routes = [
{ path: '/', name: 'home', component: Home },
{ path: '/about', name: 'about', component: About },
{ path: '/contact', name: 'contact', component: Contact }
];复制代码
看看咱们编译代码时的统计数据,每一个页面都在它们本身的文件里,但要注意到有个重要的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 不会阻塞初始页面的加载。
折叠如下(Below the “fold”)表明页面初始时不可见的部分。你能够异步加载这些内容,由于用户一般须要一两秒钟才能阅读完折叠以上的内容,尤为是在第一次访问站点时。
在这个实例应用中,我考虑把折叠线设在刊头下。那么让咱们在页面初始化时加载导航栏和刊头,它们之下的全部内容,稍后再加载。我会建立一个名叫 BelowFold 的组件,提取出相关的代码以下:
Home.vue:
<template>
<div>
<div class="jumbotron">
<h1>Jumbotron heading</h1>
...
</div>
<below-fold></below-fold>
<!--All the code below here has been put into-->
<!--into the above component-->
<!--<div class="row marketing">
<div class="col-lg-6">
<h4>Subheading</h4>
<p>Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.</p>
...
</div>
...
</div>-->
</div>
</template>
<script>
const BelowFold = () => import(
/* webpackChunkName: "below-fold" */ './BelowFold.vue'
);
export default {
...
components: {
BelowFold
}
}
</script>复制代码
BelowFold.vue:
<template>
<div class="row marketing">
<div class="col-lg-6">
<h4>Subheading</h4>
<p>Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.</p>
...
</div>
...
</div>
</template>复制代码
当咱们编译代码时,能够看到 below-fold 被打包成了单独的文件:
提示:below-fold 小到只有1.36k,看起来彷佛不值得把它单独分离出来。由于如今只是一个很小的演示应用。在真实的应用中,页面的大部份内容都在折叠如下,所以可能有大量的代码,它包括 JS、CSS 以及全部子组件。
另外一个选择方案是按条件加载。好比:模态框、Tab页、菜单等。
这个应用有个模态框,当你按下"Sign up today"按钮时会弹出它:
和以前同样,咱们只是将模态框代码移动到它本身的单个文件组件中:
Home.vue:
<template>
<div>
<div class="jumbotron">...</div>
<below-fold></below-fold>
<home-modal v-if="show" :show="show"></home-modal>
</div>
</template>
<script>
const BelowFold = () => import(
/* webpackChunkName: "below-fold" */ './BelowFold.vue'
);
const HomeModal = () => import(
/* webpackChunkName: "modal" */ './HomeModal.vue'
);
export default {
data() {
return {
show: false
}
},
components: {
HomeModal,
BelowFold
}
}
</script>复制代码
HomeModal.vue:
<template>
<modal v-model="show" effect="fade">...</modal>
</template>
<script>
import Modal from 'vue-strap/src/Modal.vue';
export default {
props: ['show'],
components: {
Modal
}
}
</script>复制代码
注意我在模态框上加了 v-if
。布尔值 show
用来开启/关闭模态框,而且它也用来判断是否渲染模态框自己。由于初始化页面时 show
为 false
,只有当模态框打开时,才会下载代码。
这很合适,由于若是用户没有打开模态框,那这块代码是不会下载的。惟一的缺点是:它有很小的用户体验成本,当用户按下按钮后必须等待文件下载完成。
再次编译,下面是如今的输出结果:
啊哈,咱们又节省了5KB的首屏流量...
除了以上三种代码分割的方法,我相信必定还有其余方法去实现,只要你运用本身的想象力!
本文译者:余震(Freak)
译文出处:Rockjins Blog
版权声明:本博客全部文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN许可协议。转载请注明出处!