在研究iView的源码时,看到各个组件用到的JS都是按需加载的,也就是懒加载,如下:
https://file.iviewui.com/dist/vendors.a175e0b04162b38943ca.js
https://file.iviewui.com/dist/main.a175e0b04162b38943ca.js
https://file.iviewui.com/dist/69.a175e0b04162b38943ca.chunk.js
https://file.iviewui.com/dist/98.a175e0b04162b38943ca.chunk.js
https://file.iviewui.com/dist/10.a175e0b04162b38943ca.chunk.js
https://file.iviewui.com/dist/118.a175e0b04162b38943ca.chunk.js
https://file.iviewui.com/dist/119.a175e0b04162b38943ca.chunk.js
https://file.iviewui.com/dist/134.a175e0b04162b38943ca.chunk.js
https://file.iviewui.com/dist/121.a175e0b04162b38943ca.chunk.js
之前在另一个页面埋点的项目中使用 webpack 的 require.ensure() 可以实现把首次用不到的打包成 [name].chunk.js 的 方式用到再加载,即懒加载。可是搜了下,iView Doc的源码,根本没找到 require.ensure()。 继续研究,发现每次切换 router 才会加载所需JS,就推测到应该是由 router.js 控制的,然后找到如下代码:
{
path: '/components/input',
meta: {
title: '输入框 Input'
},
component: (resolve) => require(['./views/components/input.vue'], resolve)
},
{
path: '/components/input-en',
meta: {
title: 'Input'
},
component: (resolve) => require(['./views/components/input-en.vue'], resolve)
},
{
path: '/components/radio',
meta: {
title: '单选框 Radio'
},
component: (resolve) => require(['./views/components/radio.vue'], resolve)
},
没看到 require.ensure() ,只有require([..], fn),这个和之前的常规用法不同,以前常会类似下面的用法:
import Input from './component/input.vue'
...
{
path: '/components/input',
meta: {
title: '输入框 Input'
},
component: Input
},
...
找了下官网 https://cn.vuejs.org/v2/guide/components-dynamic-async.html 查阅到如下关于 “异步组件” 的描述:
在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。例如:
Vue.component('async-example', function (resolve, reject) {
setTimeout(function () {
// 向 `resolve` 回调传递组件定义
resolve({
template: '<div>I am async!</div>'
})
}, 1000)
})
如你所见,这个工厂函数会收到一个 resolve 回调,这个回调函数会在你从服务器得到组件定义的时候被调用。你也可以调用 reject(reason) 来表示加载失败。这里的 setTimeout 是为了演示用的,如何获取组件取决于你自己。一个推荐的做法是将异步组件和 webpack 的 code-splitting 功能一起配合使用:
Vue.component('async-webpack-example', function (resolve) {
// 这个特殊的 `require` 语法将会告诉 webpack
// 自动将你的构建代码切割成多个包,这些包
// 会通过 Ajax 请求加载
require(['./my-async-component'], resolve)
})
你也可以在工厂函数中返回一个 Promise,所以把 webpack 2 和 ES2015 语法加在一起,我们可以写成这样:
Vue.component(
'async-webpack-example',
// 这个 `import` 函数会返回一个 `Promise` 对象。
() => import('./my-async-component')
)
当使用局部注册的时候,你也可以直接提供一个返回 Promise 的函数:
new Vue({
// ...
components: {
'my-component': () => import('./my-async-component')
}
})
由于 import() 这种方式非原生用法,因此需要使用 babel-plugin-syntax-dynamic-import 插件, 安装如下:
我们还希望能够在项目对一些组件进行懒加载,所以还需要一个Babel插件:
npm i babel-plugin-syntax-dynamic-import -D
在 .babelrc 文件中加入plugins配置:
{
"presets": [
"@babel/preset-env"
],
"plugins": [
"syntax-dynamic-import"
]
}
或者
use: [{
loader: 'babel-loader',
options: {
presets: [['es2015', {modules: false}]],
plugins: ['syntax-dynamic-import']
}
}]
........... 至此结束。
一些查到的其他资料:
配合webpack支持的异步加载方法
resolve => require([URL], resolve), 支持性好
() => system.import(URL) , webpack2官网上已经声明将逐渐废除, 不推荐使用
() => import(URL), webpack2官网推荐使用, 属于es7范畴, 需要配合babel的syntax-dynamic-import插件使用, 具体使用方法如下
npm安装包:
npm install --save-dev babel-core babel-loader babel-plugin-syntax-dynamic-import babel-preset-es2015
代码:
use: [{
loader: 'babel-loader',
options: {
presets: [['es2015', {modules: false}]],
plugins: ['syntax-dynamic-import']
}
}]
四、具体实例中实现懒加载
1、路由中配置异步组件
export default new Router({
routes: [
{
mode: 'history',
path: '/my',
name: 'my',
component: resolve => require(['../page/my/my.vue'], resolve),//懒加载
},
]
})
参考链接:
https://cn.vuejs.org/v2/guide/components-dynamic-async.html https://www.cnblogs.com/zhensg123/p/7671129.html https://www.cnblogs.com/zhanyishu/p/6587571.html https://segmentfault.com/a/1190000017898866?utm_source=tag-newest