For a Single Page Application (SPA
), when building, the JavaScript
package can become very large, affecting page load speed. The components corresponding to different routes are split into different code blocks. Then, when a route is accessed, the corresponding component is loaded, which is called route lazy loading.
Vue
allows you to define your components using a factory function. This factory function will asynchronously resolve your component definition. Vue
will only trigger this factory function when the component needs to be rendered, and will cache the result for future re-rendering.
Vue.component("async-example", function (resolve, reject) {
setTimeout(function() {
// Pass the component definition to the `resolve` callback
resolve({
template: "<div>I am async!</div>"
})
}, 1000)
})
This factory function will receive a resolve
callback. This callback function will be called when you receive the component definition from the server, and reject(reason)
can also be called to indicate a failed load. The setTimeout
here is just used to demonstrate the asynchronous transfer of component definition. Combining asynchronous components with webpack
's code-splitting
functionality can achieve lazy loading of components.
Vue.component("async-webpack-example", function (resolve) {
// This special `require` syntax will instruct webpack
// to automatically split your build code into multiple bundles,
// which will be loaded via Ajax requests
require(["./my-async-component"], resolve)
})
You can also return a Promise
in the factory function, combining webpack 2
and ES2015
syntax.
Vue.component(
"async-webpack-example",
// This dynamic import will return a `Promise` object.
() => import("./my-async-component")
)
In fact, in the configuration of Vue-Router
, you can directly combine Vue
's asynchronous components with Webpack
's code-splitting feature to achieve lazy loading of route components, with each component generating a separate js
file after packaging.
{
path: "/example",
name: "example",
// After packaging, each component generates a separate chunk file
component: resolve => require(["@/views/example.vue"], resolve)
}
In Webpack2
, you can use dynamic import
syntax to define code split points. This method is also recommended by the official. If using Babel
, you need to add the syntax-dynamic-import
plugin to allow Babel
to correctly parse the syntax.
// Default: package each component into a separate js file
const example = () => import("@/views/example.vue")
Sometimes, we may want to package all components under a certain route in the same asynchronous chunk. You need to use a special comment syntax to provide a chunk name
when using webpack > 2.4
.
const example1 = () => import(/* webpackChunkName: "Example" */ "@/views/example1.vue");
const example2 = () => import(/* webpackChunkName: "Example" */ "@/views/example2.vue");
In fact, in the configuration of Vue-Router
, you can directly define lazy loading.
{
path: "/example",
name: "example",
// After packaging, each component generates a separate chunk file
component: () => import("@/views/example.vue")
}
Using webpack
's require.ensure
can also achieve on-demand loading, and specifying the same chunkName
for multiple routes will also merge and package them into a single js
file.
// require.ensure(dependencies: String[], callback: function(require), chunkName: String)
{
path: "/example1",
name: "example1",
component: resolve => require.ensure([], () => resolve(require("@/views/example1.vue")), "Example")
},
{
path: "/example2",
name: "example2",
component: resolve => require.ensure([], () => resolve(require("@/views/example2.vue")), "Example")
}
https://github.com/WindrunnerMax/EveryDay
https://zhuanlan.zhihu.com/p/46843949
https://www.jianshu.com/p/c27b1640a01b
https://juejin.im/post/6844904025746309127
https://juejin.im/post/6844904013842874376
https://segmentfault.com/a/1190000011519350
https://cn.vuejs.org/v2/guide/components-dynamic-async.html
https://router.vuejs.org/zh/guide/advanced/lazy-loading.htm