当打包构建应用时,javascript包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
结合Vue的异步组件和webpack的code splitting feature,轻松实现路由组件的懒加载。
我们要做的就是把路由对应的组件定义成异步组件:
const Foo = resolve => { // require.ensure 是webpack的特殊语法,用来设置code-split point // 代码分块 require.ensure(['./Foo.vue'], () => { resolve(require('./Foo.vue')) }) }
还有另外一种代码分块的语法,使用AMD风格的require,更为简单:
const Foo = resolve => require(['./Foo.vue'], resolve)
只是引入模块的方式由原来的 import Foo from './Foo'
改变成了如上的方式,这样就可以根据不同路由来加载不同的模块了,不需要改变任何路由配置,跟之前一样使用Foo:
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo } ] })
实际项目中一般一个路由下会有多个组件,或者组件下有多个子组件,这里就需要把组件按组分块了。
把某个路由下的所有组件都打包在同个异步chunk中。只需要给chunk命名,提供require.ensure第三个参数作为chunk的名称:
const Foo = r => require.ensure([], () => r(require('./Foo.vue')), 'group-foo') const Bar = r => require.ensure([], () => r(require('./Bar.vue')), 'group-foo') const Baz = r => require.ensure([], () => r(require('./Baz.vue')), 'group-foo')
Webpack将相同chunk下的所有异步模块打包到一个异步块里面 -- 这也意味着我们无须明确列表require.ensure的依懒(传空数组就行)
懒加载的目的其实就是为了减少单个js文件的大小,如果所有文件都打包到bundle.js的话,会是一个非常庞大的js文件,而且随着项目内容的变多,这个文件也会越来越大,使用懒加载就可以将文件分割成不同的.js文件,实现按需加载!
requre.ensure()的坑点
.空数组作为参数
require.ensure([], function(require){ require('./a.js') })
以上代码保证了拆分点被创建,而且a.js被webpack分开打包,不会打到主文件中。
.依懒作为参数
require.ensure(['./a.js'], function(require) { require('./b.js') })
上面的代码,a.js 和 b.js 会被打包到一起,而且从主文件束中拆分出来。但只有b.js的内容被执行。a.js的内容仅仅是可以被使用,但并没有被输出。
想去执行a.js,我们需要异步的引用它,如require('./a.js'),让它的javascript被执行。第三个参数的意义就是把chunk名相同的文件打包到一起!
require.ensure([], function(require) { require('./a.js') }, 'group-ab') require.ensure([], function(require) { require('./b.js') }, 'group-ab')
如上所示,就可以实现a.js 和 b.js打包在一起,a.js的内容也能被执行!