Vue.js中用webpack合并打包多个组件并实现按需加载


Posted in Javascript onFebruary 17, 2017

前言

随着移动设备的升级、网络速度的提高,用户对于web应用的要求越来越高,web应用要提供的功能越来越。功能的增加导致的最直观的后果就是资源文件越来越大。为了维护越来越庞大的客户端代码,提出了模块化的概念来组织代码。webpack作为一种模块化打包工具,随着react的流行也越来越流行。

使用 Vue 开发项目时,如果要使用其单文件组件特性,必然要使用 webpack 或者 browserify 进行打包,对于大型应用,为了提升加载速度,可以使用 webpack 的 code split 功能进行分割打包,生成较小的模块并按需加载,这在 Vue 文档及 vue-router 文档中均有介绍:Async Components、Lazy Loading。

webpack 的 code split 可以使用 webpack 的 require.ensure 特殊语法或者使用 AMD 风格的 callback-require 语法,以 AMD 风格的 callback-require 语法为例——

全局注册 Async Component:

let myAsyncComponent = resolve => {
 require(['./my-async-component'], resolve)
}
Vue.component('async-webpack-example', myAsyncComponent)

局部注册 Async Component,单文件组件中 script 块内容:

let myAsyncComponent = resolve => {
 require(['./my-async-component'], resolve)
}

// Vue 扩展实例选项,其他选项略
export default {
 components: {
 'async-webpack-example': myAsyncComponent
 }
}

在使用 vue-router 时,为实现不同路由下的组件异步加载,在路由映射中可以使用同样的方式来设置路由项的 component 属性。

这里的 myAsyncComponent 被定义为一个工厂函数,在需要时才会以 Vue 或者 vue-router 定义的用于解析组件选项的 resolve 回调函数(是的,在 Vue 和 vue-router 中有两个不同的解析组件选项的函数)为参数执行 callback-require 函数(resolve 回调函数的参数是组件选项),这样,在执行打包脚本时,my-async-component.vue 文件会被单独打包成一个文件,并且仅当该组件被使用时才会加载。

当要求异步加载的组件较多时,将会生成更多的单个文件,对于前端性能而言,虽然每个文件更小了,但可能意味着更多的网络连接建立和关闭的开销,因此在前端优化的实践中,通常需要在文件数量和单个文件大小之间取得平衡。

本文介绍如何将多个组件合并打包成一个单独的文件,一方面可以减少代码块的数量,另一方面,如果合并打包的这些组件在不同地方多次重复使用,由于 Vue 的缓存机制,可以加快后续组件的加载速度,并且如果这些通用组件长时间不会变化(如 UI 相关的组件),打包生成的文件也长期不会变化,可以充分利用浏览器的缓存功能,实现前端加载速度的优化。

先上效果图,在使用 vue-router 的 SPA 应用中,将除根路由之外的路由项对应的 ComponentA、ComponentB、ComponentC 等三个组件合并打包成一个文件。初次加载页面时,从开发者工具的 Network 面板上可以看到,此时未加载包含 ComponentA、ComponentB、ComponentC 这三个组件的 0.a5a1bae6addad442ac82.js 文件,当点击 Page A 链接时,加载了该文件,然后再点击 Page B、Page C 链接时,没有重新加载该文件。

Vue.js中用webpack合并打包多个组件并实现按需加载

我们首先通过 vue-cli 命令行工具使用 webpack 项目模板创建一个包含 vue-router 的项目,在其 src/components 目录下创建一个 CommonComponents 目录,在该目录中创建 ComponentA、ComponentB、ComponentC 这三个组件。

Vue.js中用webpack合并打包多个组件并实现按需加载

同时在 CommonComponents 目录下创建 index.js,其内容如下:

exports.ComponentA = require('./ComponentA')
exports.ComponentB = require('./ComponentB')
exports.ComponentC = require('./ComponentC')

这样,我们只需要使用 webpack 的 require.ensure 特殊语法或者使用 AMD 风格的 callback-require 语法异步加载 CommonComponents 目录下的 index.js,在使用 webpack 进行打包时,就可以实现将 ComponentA、ComponentB、ComponentC 这三个组件合并打包。以 AMD 风格的 callback-require 语法为例示范如下,这里的 callback 回调函数的形式没有任何特殊要求。

require(['component/CommonComponents'], function (CommonComponents) {
 // do whatever you want with CommonComponents
})

component/CommonComponents 模块加载成功时,这里的回调函数中的 CommonComponents 参数将会是一个包含 ComponentA、ComponentB、ComponentC 这三个组件选项的对象。

在定义异步解析组件时,我们使用的是一个工厂函数 resolve => {require(['./my-async-component'], resolve)},如果需要在路由配置文件中添加 component 属性为 ComponentA 组件的路由项,应该定义什么样的工厂函数呢?记住这里的 resolve 是一个用于解析组件选项的回调函数,其参数是所获取的组件选项,而上一段代码中的 CommonComponents 恰好是包含若干个组件选项的对象,因此我们可以将 CommonComponents 的子属性作为参数用于 resolve 调用,我们编写一个函数 getCommonComponent,用于根据组件名称返回获取相应的组件选项的工厂函数。

let getCommonComponent = componentName => resolve => require(['components/CommonComponents'], components => resolve(components[componentName]))

在组件模板或者路由映射等使用其中某一个组件的地方,可以使用类似于 getCommonComponent('ComponentA') 这样的函数调用进行组件设置,在路由映射中的使用示例如下:

routes: [
 {
 path: '/',
 name: 'Hello',
 component: Hello
 },
 {
 path: '/a',
 name: 'A',
 component: getCommonComponent('ComponentA')
 },
 {
 path: '/b',
 name: 'B',
 component: getCommonComponent('ComponentB')
 },
 {
 path: '/c',
 name: 'C',
 component: getCommonComponent('ComponentC')
 }
]

最终打包生成的文件列表如下图所示,其中的 0.a5a1bae6addad442ac82.js 包含了 ComponentA、ComponentB、ComponentC 这三个组件。

Vue.js中用webpack合并打包多个组件并实现按需加载

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
js 控制下拉菜单刷新的方法
Mar 03 Javascript
javascript中RegExp保留小数点后几位数的方法分享
Aug 13 Javascript
使用jquery操作session方法分享
Jan 22 Javascript
jQuery中大家不太了解的几个方法
Mar 04 Javascript
基于JavaScript代码实现pc与手机之间的跳转
Dec 23 Javascript
javascript Promise简单学习使用方法小结
May 17 Javascript
JS实现鼠标框选效果完整实例
Jun 20 Javascript
JavaScript基于Dom操作实现查找、修改HTML元素的内容及属性的方法
Jan 20 Javascript
Vue.js 60分钟快速入门教程
Mar 28 Javascript
原生javascript上传图片带进度条【实例分享】
Apr 06 Javascript
EasyUI Tree树组件无限循环的解决方法
Sep 27 Javascript
jquery动态添加以及遍历option并获取特定样式名称的option方法
Jan 29 jQuery
浅析JavaScript中var that=this
Feb 17 #Javascript
Bootstrap表格使用方法详解
Feb 17 #Javascript
BootStrap与Select2使用小结
Feb 17 #Javascript
解决给dom元素绑定click等事件无效问题的方法
Feb 17 #Javascript
Vue.js原理分析之observer模块详解
Feb 17 #Javascript
BootStrap的select2既可以查询又可以输入的实现代码
Feb 17 #Javascript
Bootstrap表单使用方法详解
Feb 17 #Javascript
You might like
扩展你的 PHP 之入门篇
2006/12/04 PHP
php中如何防止表单的重复提交
2013/08/02 PHP
php多线程并发实现方法
2016/09/30 PHP
通过PHP的Wrapper无缝迁移原有项目到新服务的实现方法
2020/04/02 PHP
19个很有用的 JavaScript库推荐
2011/06/27 Javascript
编写简单的jQuery提示插件
2014/12/21 Javascript
jQuery实现信息提示框(带有圆角框与动画)效果
2015/08/07 Javascript
JavaScript实现为input与textarea自定义hover,focus效果的方法
2015/08/21 Javascript
原生的强大DOM选择器querySelector介绍
2016/12/21 Javascript
微信小程序 登录实例详解
2017/01/16 Javascript
vue2.0数据双向绑定与表单bootstrap+vue组件
2017/02/27 Javascript
Node.js中的http请求客户端示例(request client)
2017/05/04 Javascript
原生JavaScript实现的简单省市县三级联动功能示例
2017/05/27 Javascript
详解Angular结合zTree异步加载节点数据
2018/01/20 Javascript
Vue使用高德地图搭建实时公交应用功能(地图 + 附近站点+线路详情 + 输入提示+换乘详情)
2018/05/16 Javascript
React组件重构之嵌套+继承及高阶组件详解
2018/07/19 Javascript
Vue.js 时间转换代码及时间戳转时间字符串
2018/10/16 Javascript
浅析Angular 实现一个repeat指令的方法
2019/07/21 Javascript
如何利用nodejs自动定时发送邮件提醒(超实用)
2020/12/01 NodeJs
[42:25]2018DOTA2亚洲邀请赛 4.5 淘汰赛 LGD vs Liquid 第三场
2018/04/06 DOTA
[40:12]Liquid vs Chaos 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
如何运行Python程序的方法
2013/04/21 Python
python消费kafka数据批量插入到es的方法
2018/12/27 Python
浅谈Python中eval的强大与危害
2019/03/13 Python
python中栈的原理及实现方法示例
2019/11/27 Python
CSS3 box-sizing属性
2009/04/17 HTML / CSS
使用CSS3实现一个3D相册效果实例
2016/12/03 HTML / CSS
彩色的非洲教学反思
2014/02/18 职场文书
开学典礼演讲稿
2014/05/23 职场文书
分公司负责人任命书
2014/06/04 职场文书
班主任2015新年寄语
2014/12/08 职场文书
《乘法分配律》教学反思
2016/02/24 职场文书
合作合同协议书
2016/03/21 职场文书
电子表的操作介绍说明书
2019/10/28 职场文书
python简单验证码识别的实现过程
2021/06/20 Python
python开发制作好看的时钟效果
2022/05/02 Python