代码分割 可以很好的提高单页面应用加载速度。用户不用等到所有代码一次加载完毕便可以很快的看到页面并与之交互。这尤其会提升移动端的用户体验,此外可以获得不错的SEO,因为Google会对加载慢的站点进行降权。
上周我写了关于如何使用Webpack分离Vue.js应用代码(注:相对简单亦无需梯子)。简单来说就是,所有包含在单文件组件里的都能很容易地被分离,因为在导入一个模块时,Webpack能创建分离点,Vue能够轻松愉快地异步读取组件。
我相信让代码分离跑起来并不难,难得是了解什么时候以及什么地方使用它。甚至可以说,在设计你的应用时,需要一种架构思想来对代码进行分离。
本文我将介绍三种用于Vue.js单页面应用的代码分离方法:
- 按页面
- 按折页
- 按条件
1. 按页面
按页面分割是显而易见的,这个简单的例子中有三个页面:
一旦我们确定每个页面对应着它自己的单页面组件,例如:Home.vue, About.vue, Contact.vue等,那么我们就可以用Webpack的动态
import
方法逐一分离到独立的生成文件里。当用户访问不同页面时,Webpack会异步读取需要的页面文件。如果你正使用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 }
];
看一下生成统计,每个页面各居其位。但要留意有个叫做build_main.js的打包文件,它包含了所有的通用代码以及异步加载的其它文件逻辑,无论用户访问哪些路由它都需要被加载。
现在好比我通过http://localhost:8080/#/contact地址读取到Contact页面,当切换到Chrome Network标签页时会发现下面的文件已经加载:
注意那个build_main.js的initiator是index,这表示index.html需要该脚本,这也是我们希望的。但是build_1.js的initator是bootstrap_a877... 这是Webpack负责异步读取文件的脚本,当使用Webpack的动态
import
方法时该脚本会被自动生成。重点是build_1.js不会阻止初始页面加载。
2.折页之下
“折页”之下是说当页面一开始加载时该页面中那些在视窗中见不到的部分。因为用户通常会在下拉之前花上一到两秒阅读“折页”上面的内容,所以可以异步读取这些内容,特别是在他们初次访问该站时。
本例中我假设“折页”的“折线”位于报头下方,导航栏和报头会在页面一开始就加载,下面的所有内容都会在后面加载。现在创建一个叫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.36kB)看起来不值得分离出来。这仅仅是因为这是个有着很少内容的demo,真正的应用,页面大量的内容会位于“折页”里,有可能会是大量包括CSS或者JS文件在内的子组件。
3.条件内容
代码分离另一个不错的选择是有条件地显示内容。例如modal窗口,tabs,下拉菜单等等。
下面的应用在点击“今日登陆”按钮后会有个modal窗口:
老惯例,我们先看看这个单文件组件的代码:
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
放在modal中了。布尔值show
控制modal的开启/关闭状态,同时它也有条件的渲染modal组件。由于页面读到它为false,因此代码只会在modal是开启状态下加载。
这很酷不是吗?如果用户压根儿没有打开modal,他们就永远不会下载这些代码。只是有些小小的用户体验上的缺点:用户必须要等到他们按下按钮后代码才会加载进来。
再次生成后,会有下面这些输出信息:
另外的 ~5kB我们不必提前加载。
结论
这些就是在构建一个应用的时候代码分离的三种思想。相信利用你的想象力你还会发现其它方法。
获取最新Vue.js文章、教程以及酷炫项目点击http://vuejsdevelopers.com/newsletter/(貌似已经404了😓)
网友评论