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

对于如今前端插件的频繁更新,因此多多少少要对组件化有点了解,下面这篇文章主要给你们介绍了在Vue.js中用webpack合并打包多个组件并实现按需加载的相关资料,须要的朋友能够参考下。
 

前言html

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

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

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

全局注册 Async Component:webpack

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

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

 
1
2
3
4
5
6
7
8
9
10
let myAsyncComponent = resolve => {
  require([ './my-async-component' ], resolve)
}
 
// Vue 扩展实例选项,其余选项略
export default {
  components: {
  'async-webpack-example' : myAsyncComponent
  }
}

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

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

当要求异步加载的组件较多时,将会生成更多的单个文件,对于前端性能而言,虽然每一个文件更小了,但可能意味着更多的网络链接创建和关闭的开销,所以在前端优化的实践中,一般须要在文件数量和单个文件大小之间取得平衡。浏览器

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

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

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

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

 
1
2
3
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 回调函数的形式没有任何特殊要求。

 
1
2
3
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,用于根据组件名称返回获取相应的组件选项的工厂函数。

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

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

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 这三个组件。

相关文章
相关标签/搜索