用webpack来打包你的单页应用的一个可能的缺点是你可能会获得一个很是大的打包文件,有时甚至会有几兆大小。html
Asset | Size |
---|---|
bundle.main.js | 1.36MB |
随之带来的问题是用户在屏幕上看到任何东西以前,必需要下载整个文件并运行它。若是用户使用的是网络链接很差的设备,这个过程可能须要很长时间。
Code splitting 就是把打包文件分割成为更小的文件,容许用户在他们须要的时候下载须要的代码块的一个方法。
例如,看看这个简单的界面,咱们能够识别出这个App中不须要初始载入的部分。 vue
若是咱们延迟加载这些代码段直到初始渲染结束会怎样?它可让用户更快的看到界面并进行交互。
在这篇文章,我将向你展现如何使用Vue.js 和 Webpack将单页应用拆分红能够动态加载的更理想的大小。webpack
Code splitting 的关键就是异步组件(async components),这个组件的定义就是异步加载(包括它的模板,数据,方法等等)。
首先让咱们用component API 即 Vue.component(name, definition) 声明一个组件。不一样于将定义对象做为第二个参数,异步组件有一个函数,这个函数有两个显著的特色:web
Vue.component('async-component', (resolve) => { resolve({ template: '<div>Async Component</div>', props: [ 'myprop' ] }); });
异步组件是 Code splitting 的第一步,由于咱们如今才有了一个抽象的机制。网络
咱们还须要 webpack 的帮助,假设咱们将组件定义抽象为ES6模块文件: 架构
AsyncComponent.jsapp
export default { template: '<div>Async Component</div>', props: [ 'myprop' ] }
咱们怎么让Vue.js加载它呢?你可能会想试试这样的方法:异步
import AsyncComponent from './AsyncComponent.js'`; Vue.component('async-component', AsyncComponent);
可是这是静态的而且在编译时解析,若是咱们想要得到Code splitting 的好处,咱们须要的是在运行的应用中动态地加载。async
目前,用JavaScript来动态的加载模块是不可能的。可是,ECMAScript有一个动态模块加载函数叫作 import() 。
Webpack已经有了一个import()的实现,并将其做为一个代码分割点,在建立包时,将所请求的模块放入一个单独的文件中(一个单独的chunk,实际上,如今把它看做单独的一个文件)。
import() 将文件名做为一个参数并返回一个Promise。下面是咱们如何加载上面的模块:函数
import(/* webpackChunkName: "async-component" */ './AsyncComponent.js') .then((AsyncComponent) => { console.log(AsyncComponent.default.template); // Output: <div>Async Component</div> });
注:若是你使用Babel,你须要添加 syntax-dynamic-import 插件 以便Babel能够正确的解析。
如今,但你构建项目的时候,你会注意到这些模块出如今它本身的文件中了:
Asset | Chuck Name |
---|---|
bundle.main.js | main |
bundle.0.js | async-component |
你能够给动态导入的模块加一个名字,让它更容易识别;只需在文件名前面添加一个注释,就像我在上面的例子中所作的那样。
由于 import() 返回一个Promise,咱们能够将它和 Vue 的异步组件功能结合使用。Webpack将单独打包异步组件,并经过AJAX将其动态加载到应用程序中。
main.js
import Vue from 'vue'; Vue.component('async-component', (resolve) => { import('./AsyncComponent.js') .then((AsyncComponent) => { resolve(AsyncComponent.default); }); }); new Vue({ el: '#app' });
index.html
<div id="app"> <p>This part is included in the page load</p> <async-component></async-component> </div> <script src="bundle.main.js"></script>
页面初始加载时:
<div id="app"> <p>This part is included in the page load</p> </div>
当main.js运行的时候,它将启动异步组件模块的请求(这是自动实现的,由于 webpack 的 import() 包含了AJAX加载模块的代码)。
若是Ajax成功返回模块,Promise 完成而且渲染组件,页面将会被渲染成这样:
<div id="app"> <p>This part is included in the page load</p> <div>Async Component</div> </div>
下图能够更好地帮助你理解:
Vue 实现 Code Splitting 的特殊方式就是使用 single file component。下面是使用single file component的代码重构:
AsyncComponent.vue
<template> <div>Async Component</div> </template> <script> export default { props: [ 'myprop' ] } </script>
导入的语法也更加简洁
new Vue({ el: '#app', components: { AsyncComponent: () => import('./AsyncComponent.vue') } });
这是无关技术的部分,问题就是咱们怎么为一个app构建一个code splitting ?
最直接的方法就是按照界面来,好比,你的app上有两个界面,一个home,一个about。这两个界面是由两个组件(home.vue about.vue)构成,那么这两个组件就能够是拆分的点。
另外,你也能够对任何有条件的组件(选项卡、弹窗、下拉菜单等等)或者是footer进行拆分。
原文地址: Code Splitting with Vue.js And Webpack
译者: Damer Wang