我们先看看下面这个面试题:
vue-router第一次加载组件资源过多导致加载缓慢,如何解决?
答案是:通过路由懒加载的形式来解决这个问题
那么什么是路由懒加载呢?
懒加载也叫延迟加载,路由懒加载是利用Vue.js的异步组件和webpack的代码分割,把不同路由对应的不同组件分割成不同的代码块,当路由被访问时,再去加载对应的组件,然后每次进入一个新页面才加载该页面所需要的资源(也就是异步加载路由)
了解 Vue 的异步组件
Webpack 的代码分割功能
刚开始我们使用路由可能是下面这样(index.js)
import Vue from 'vue'
import Router from 'vue-router'
import StudentInfo from '@/components/StudentInfo'
import StudentChu from '@/components/StudentChu'
import Exam from '@/components/Exam'
import Login from '@/components/Login'
import Main from '@/components/Main'
export default new Router({
routes: [
{path: '/', name: 'login', component: Login},
{
path: '/main',
name: 'Main',
component: Main,
children:[
{path: 'stuInfo',name: 'stuInfo',component: StudentInfo},
{path: 'stuChu',name: 'stuChu',component: StudentChu},
{path: 'exam',name: 'exam',component:Exam}
]
},
]
})
router/index.js 路由相关信息,该路由文件引入了多个 .vue组件 ,然后export 导出,
执行 npm run build 会 打包为一个整体 app.js ,
如下面所示
这样一开始进入页面就会把所有的路由资源都加载,如果项目大,加载的内容就会很多,等待的时间页就会越长,导致给用户的不好的体验效果。
解决这个问题,我们把路由分模块,每次进入一个新页面才加载该页面所需要的资源(也就是异步加载路由)
我们可以像下面这样改写上面的代码
//这里就只导入 vue 和 vue-router,不需要再导入组件
import Vue from 'vue'
import Router from 'vue-router'
const Login=resolve=>require(['@/components/Login'],resolve);
const Main=resolve=>require(['@/components/Main'],resolve);
const StudentInfo=resolve=>require(['@/components/StudentInfo'],resolve);
const StudentChu=resolve=>require(['@/components/StudentChu'],resolve);
const Exam=resolve=>require(['@/components/Exam'],resolve);
//这里的写法不变
export default new Router({
routes: [
{path: '/', name: 'login', component: Login},
{
path: '/main',
name: 'Main',
component: Main,
children:[
{path: 'stuInfo',name: 'stuInfo',component: StudentInfo},
{path: 'stuChu',name: 'stuChu',component: StudentChu},
{path: 'exam',name: 'exam',component:Exam}
]
},
]
})
执行 npm run build 发现,多了很多1.xxxxx.js;2.xxxxx.js 等js文件,如下图所示
原因就是 Webpack 会将每个异步加载都打包成一个.js文件
支持分组的写法 推荐!!!
有时候我们想把某个路由下的所有组件都打包在同个异步块 (chunk) 中。只需要使用 命名 chunk,一个特殊的注释语法来提供 chunk name (需要 Webpack > 2.4)。
const Login=resolve=>require(['@/components/Login'],resolve);
const Main=resolve=>require(['@/components/Main'],resolve);
const StudentInfo = () => import(/* webpackChunkName: "group-foo" */ '@/components/StudentInfo');
const StudentChu = () => import(/* webpackChunkName: "group-foo" */ '@/components/StudentChu');
const Exam = () => import(/* webpackChunkName: "group-foo" */ '@/components/Exam');
export default new Router({
routes: [
{path: '/', name: 'login', component: Login},
{
path: '/main',
name: 'Main',
component: Main,
children:[
{path: 'stuInfo',name: 'stuInfo',component: StudentInfo},
{path: 'stuChu',name: 'stuChu',component: StudentChu},
{path: 'exam',name: 'exam',component:Exam}
]
},
]
})
还可以这样写
// r就是resolve
const centerHome = r => require.ensure([], () => r(require('../pages/home/center-home')), 'center')
const centerInfo = r => require.ensure([], () => r(require('../pages/home/center-info')), 'center')
const centerShop = r => require.ensure([], () => r(require('../pages/home/center-shop.vue')), 'center')
const router = new VueRouter({
mode: 'hash',
base: __dirname,
scrollBehavior,
routes: [
{ name:'center-home', path: '/center/home', component: centerHome },
{ name:'center-info', path: '/center/info', component: centerInfo },
{ name:'center-shop', path: '/center/shop', component: centerShop },
]
})
Webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中。
- ‘@/’ 和 ‘./’都表示当前路径
- ‘.vue’后缀可省略
- ‘center’ 是把组件按组分块打包, 可以将多个组件放入这个组中