路由懒加载解决的是一次加载的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的工厂函数:
const Foo = () => Promise.resolve({ /* 组件定义 */);
也可以提供一个定义异步组件的工厂函数:
(3)使用Webpack 2 提供的动态import
语法来定义代码分块点
import('./Foo.vue') // 返回 Promise
实际工作中更常见的是提供一个定义异步组件的工厂函数,我们只要传入组件名让Webpack找到
// 懒加载工厂函数
const lazyLoad = path => () => import(/* webpackChunkName: "view-[request]-[index]" */ `@/components/${path}.vue`);
(4)路由配置中,仍然直接引入Foo
即可
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})
如果想把某个路由下的所有组件都打包在通个异步chunk中,那么需要使用命名chunk(需要Webpack版本2.4+)。
首先需要在Webpack的output
配置项中,可以设置打包出的代码块(chunk)的名称chunkFilename
,不设置的话chunkFilename
默认使用[id].js
(文档),我们在import
中采用的特殊注释注入的webpackChunkName
是无法生效的
此时各个代码块的名字都是默认的id
:
想要我们注入的webpackChunkName
生效,就需要在Webpack的配置文件webpack.base.conf.js
中的output
选项中,添加如下配置:
module.exports = {
output: {
filename: '[name].js',
chunkFilename: '[name].chunk.js', // 新增
},
}
这样设置后,我们利用特殊的注释语法来设置的webpackChunkName
就会替换[name]
占位符
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内置的模板字符串传入变量,不支持在业务代码中手动传入值,比如说
// 懒加载工厂函数
const lazyLoad = (view, str) => () => import(`/* webpackChunkName: "view${str}-[request]-[index]" */` `@/components/demos/${view}.vue`);
这样传入str
是不能生效的
当路由增多时,routes
中每个cmponent
都需要按照如上的样式实现懒加载,并且在开发环境中使用懒加载,会导致代码更改的热跟新速度变慢,所以需要区分环境来使用路由的懒加载功能
可以对lazyLoad
函数进行优化:
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在这里。