专栏首页京程一灯VueJS + Webpack 代码分割的三种方式

VueJS + Webpack 代码分割的三种方式

对单页应用实行代码分割,是提高页面加载速度的一种很好的方式。因为用户不必在一次请求里加载完所有的代码,能够更快的看到页面并进行交互,这将会提升用户体验(特别是在移动端);同时因为 Google 会给加载缓慢的网站降权,代码分割也对 SEO 有好处。

上周我写过一篇关于 用 Webpack 对 Vue.js 应用进行代码分割 的文章。简单来说,在单文件组件里引入的任何东西都能轻松的实行代码分割,因为 Webpack 能在导入模块的时候创建分割点,同时 Vue 能很方便的对一个组件进行异步加载。

我认为,实施代码分割并不难,难在搞清楚在什么时候、什么地方进行。甚至可以说,代码分割需要在程序设计的时候,有良好的应用架构。

在本文中,我将提供 Vue.js 单页应用进行代码分割的三种思路:

  • 按页面分割
  • 使用折叠
  • 按条件分割

注:原文来自 Vue.js 开发者博客 2017/07/08

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 页面 。当查看浏览器的“网络”标签时,发现下面这些文件被加载了:

注意:build_main.js 是由 (index) 触发加载的,这意味着 index.html 如期的请求了这个脚本;但是,build_1.js 的触发器却是 bootstrap_a877… 这个文件是 Webpack 负责异步加载文件的脚本,它在你使用 Webpack “动态导入函数” 的时候就被添加进来到构建中了。关键的一点是,build_1.js 并不会阻塞初始页面的加载。

2. 折叠之下

“折叠” 之下,是指页面初次加载时,视图的不可见部分。用户通常会花费 1~2 秒来浏览可视区域,特别是第一次访问网站的时候(可能更久),之后才开始向下滑动页面。这个时候,你可以异步加载剩余的内容。

在下面这个应用示例当中,我考虑将折叠线放到报头下方。所以,我们在页面最开始加载的时候引入导航条和报头,之后的代码将在稍后加载。现在我创建了一个名为“BelowFold”的组件,相关标记抽象如下所示:

 <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>
 <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),而且看起来没有必要把它分割出来。只因为,这是一个很少内容的演示应用;在真实的应用里,大多数页面都需要折叠;因此,任意子组件中的 CSS 和 JS 文件中,都可能会包含大量的代码。

3. 条件展示内容

代码分割另一种比较好的备选方式,是按条件展示。比如:模态框、标签页、下拉菜单之类。

下面这个应用,在点击 “Sign up today” 按钮的时候,会弹出一个模态框:

在此之前,我们已经把模态框的代码放到一个单文件组件里了:

 <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>
 | <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 这个变量。一方面用来控制模态框是否显示,同时也决定了是否应该渲染模态框组件。当页面加载的时候,它的值为 false,模态框的代码只有当它显示的时候才会被加载。

最酷的是,如果用户永远不打开这个模态框,他就永远不必下载这部分代码!但是也有一点不好,可能会增加很小的用户体验成本:用户点击按钮后,需要等待代码文件下载完成。

我们再重新构建一次,结果如下图所示:

大约 5KB 的文件我们不必提前加载。

结论

以上三种,就是进行代码分割的架构设计思路。我确定,还有其它一些你能想到的的实现方式。


往期精选文章

ES6中一些超级好用的内置方法

浅谈web自适应

使用Three.js制作酷炫无比的无穷隧道特效

一个治愈JavaScript疲劳的学习计划

全栈工程师技能大全

WEB前端性能优化常见方法

一小时内搭建一个全栈Web应用框架

干货:CSS 专业技巧

四步实现React页面过渡动画效果

让你分分钟理解 JavaScript 闭包


小手一抖,资料全有。长按二维码关注京程一灯,阅读更多技术文章和业界动态。

本文分享自微信公众号 - 京程一灯(jingchengyideng)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-09-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 微信小程序商城开发---真机测试有用!!!!

    第一部分(黑色框)是pages是整个里的页面,每添加页面一个页面,都要把路径写在这里:

    疯狂的技术宅
  • 提高页面的加载速度的几个小技巧[每日前端夜话0x3F]

    为你网站的用户留下良好的第一印象是非常必要的。随着商业领域的竞争,拥有一个吸引人的网站可以帮助你脱颖而出。研究表明,如果加载时间超过3秒,会有 40% 的用户放...

    疯狂的技术宅
  • 黑客是怎样写JS的:你不知道的JavaScript用法

    注* XSS攻击即Cross Site Scripting,通常在网页链接地址Url中注入JS代码来达到攻击手段,很多大厂都中过招,如:Twitter,新浪微博...

    疯狂的技术宅
  • 从“CI搭建兽”到“流水线即代码”操练目的准备工作CI搭建兽的辛苦手工工作10行代码搞定“CI搭建兽”的全部手工工作部署流水线与单件流

    本文是2017年3月13日晚9点在“AHA面对面”线上分享的“单件流的力量-伍斌_Ben面对面”的操练步骤,这里是报名链接。

    吾真本
  • win10环境git bash使用添加.gitignore将文件提交到本地git缓存提交远程多人协作中打标签标签提交

    JavaEdge
  • Java命令之javap初探

    javap是jdk自带的一个工具在jdk安装目录的/bin下面可以找到,可以对代码反编译,也可以查看java编译器生成的字节码,对代码的执行过程进行分析,了解j...

    haifeiWu
  • JS相关概念

    小胖
  • 程序员如何高效学习

    最近看了一篇文章 在 2016 年学 JavaScript 是一种什么样的体验?。看完之后真是深有体会。以前上大学的时候觉得前端比较简单,最近入坑之后发现东西真...

    :::::::
  • Java 的 CAS原理

    在计算机科学中,比较和交换(Conmpare And Swap)是用于实现多线程同步的原子指令。它将内存位置的内容与给定值进行比较,只有在相同的情况下,将该内存...

    用户3467126
  • Flask-SocketIO 文档译文

    專 欄 ❈译者:詹聪聪 投稿 邮箱: zhancongc@gmail.com❈—— 序言: 本人工作中需要用到flask-socketio,在学习英文文档时...

    Python中文社区

扫码关注云+社区

领取腾讯云代金券