VueRouter04 路由懒加载

Vue router 路由懒加载学习笔记。

路由懒加载

路由懒加载解决的是一次加载的JS包过大的问题,将整个的JS包按照不同的路由对应的组件分割成为不同的代码块,路由访问的时候再加载对应的组件

这样的好处就是首次加载时的速度很加快,但是路由切换的过程,由于组件本身也需要通过网络请求获取,所以性能会降低

实现需要借助Vue的异步组件和Webpack的代码分割功能

实践

(1)配置Babel

如果使用了Babel,需要安装syntax-dynamic-import插件,才可以使Babel正确解析下面的语法。Babel@6需要使用babel-plugin-syntax-dynamic-import,Babel@7使用@babel/plugin-syntax-dynamic-import

同时为了防止Eslint报错:Parsing error: Unexpected token import,需要使用babel-eslint,方法参考这里

(2)需要将异步组件定义为一个返回Promise的工厂函数:

1
const Foo = () => Promise.resolve({ /* 组件定义 */);

也可以提供一个定义异步组件的工厂函数:

(3)使用Webpack 2 提供的动态import语法来定义代码分块点

1
import('./Foo.vue') // 返回 Promise

实际工作中更常见的是提供一个定义异步组件的工厂函数,我们只要传入组件名让Webpack找到

1
2
// 懒加载工厂函数
const lazyLoad = path => () => import(/* webpackChunkName: "view-[request]-[index]" */ `@/components/${path}.vue`);

(4)路由配置中,仍然直接引入Foo即可

1
2
3
4
5
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})

命名Chunk

如果想把某个路由下的所有组件都打包在通个异步chunk中,那么需要使用命名chunk(需要Webpack版本2.4+)。

首先需要在Webpack的output配置项中,可以设置打包出的代码块(chunk)的名称chunkFilename,不设置的话chunkFilename默认使用[id].js文档),我们在import中采用的特殊注释注入的webpackChunkName是无法生效的

此时各个代码块的名字都是默认的id

想要我们注入的webpackChunkName生效,就需要在Webpack的配置文件webpack.base.conf.js中的output选项中,添加如下配置:

1
2
3
4
5
6
module.exports = {
output: {
filename: '[name].js',
chunkFilename: '[name].chunk.js', // 新增
},
}

这样设置后,我们利用特殊的注释语法来设置的webpackChunkName就会替换[name]占位符

1
2
3
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')

这样三个组件会打打包到同一个chunk中,不会再被分割,也就不会动态加载。

也可以在/* webpackChunkName: "group-foo" */中使用Webpack提供的内置的模板字符串

一般可以使用/* webpackChunkName: "view-[request]-[index]" */request并没有在上面的模板中列出来,但是它可以输出我们请求这个模板的路径:

这样设置对于调试显示信息可能更全一点,要注意的事是,这个webpackChunkName的设置只能通过Webpack内置的模板字符串传入变量,不支持在业务代码中手动传入值,比如说

1
2
// 懒加载工厂函数
const lazyLoad = (view, str) => () => import(`/* webpackChunkName: "view${str}-[request]-[index]" */` `@/components/demos/${view}.vue`);

这样传入str是不能生效的

优化

当路由增多时,routes中每个cmponent都需要按照如上的样式实现懒加载,并且在开发环境中使用懒加载,会导致代码更改的热跟新速度变慢,所以需要区分环境来使用路由的懒加载功能

可以对lazyLoad函数进行优化:

1
2
3
4
5
6
7
const lazyLoad = path => {
if (process.env.NODE_ENV === 'development') {
const comp = require(`@/pages/${path}.vue`);
return comp.default || comp
}
return () => import(/* webpackChunkName: "view-[request]-[index]" */ `@/pages/${path}.vue`);
};

懒加载完整的Demo在这里

参考