|
1 | 1 | # Lazy Loading Routes
|
2 | 2 |
|
3 |
| -When you are using bundlers like Webpack or Browserify, it's trivially easy to |
4 |
| -lazy-load a route component using Vue.js' built-in |
5 |
| -[async component functionality](http://vuejs.org/guide/components.html#Async-Components). |
6 |
| -Instead of directly defining your route component, you define it as a function |
7 |
| -that will asynchronously resolve the actual component definition: |
| 3 | +When building apps with a bundler, the JavaScript bundle can become quite large and thus affecting page load time. It would be more efficient if we can split each route's components into a separate chunk, and only load them when the route is visited. |
8 | 4 |
|
9 |
| -``` js |
10 |
| -const router = new VueRouter({ |
11 |
| - routes: [ |
12 |
| - { |
13 |
| - path: '/async', |
14 |
| - component: function (resolve) { |
15 |
| - // somehow retrieve your component definition from server... |
16 |
| - resolve(MyComponent) |
17 |
| - } |
18 |
| - } |
19 |
| - ] |
20 |
| -}) |
21 |
| -``` |
| 5 | +Combining Vue's [async component feature](http://vuejs.org/guide/components.html#Async-Components) and Webpack's [code splitting feature](https://webpack.github.io/docs/code-splitting.html), it's trivially easy to |
| 6 | +lazy-load route components. |
22 | 7 |
|
23 |
| -Now, manually handling component retrieval is less than ideal, but bundlers like |
24 |
| -Webpack & Browserify both provides ways to make it easier. |
| 8 | +All we need to do is defining our route components as async components: |
25 | 9 |
|
26 |
| -### Webpack |
| 10 | +``` js |
| 11 | +const Foo = resolve => { |
| 12 | + // require.ensure is Webpack's special syntax for a code-split point. |
| 13 | + require.ensure(['./Foo.vue'], () => { |
| 14 | + resolve(require('./Foo.vue')) |
| 15 | + }) |
| 16 | +} |
| 17 | +``` |
27 | 18 |
|
28 |
| -Webpack has built-in support for async code-splitting. You can use the AMD-like |
29 |
| -`require` syntax in your code to indicate an async code-split point: |
| 19 | +There's also an alternative code-split syntax using AMD style require, so this can be simplified to: |
30 | 20 |
|
31 | 21 | ``` js
|
32 |
| -require(['./MyComponent.vue'], function (MyComponent) { |
33 |
| - // code here runs after MyComponent.vue is asynchronously loaded. |
34 |
| -}) |
| 22 | +const Foo = resolve => require(['./Foo.vue'], resolve) |
35 | 23 | ```
|
36 | 24 |
|
37 |
| -Combined with the router it can simply look like this: |
| 25 | +Nothing needs to change in the route config, just use `Foo` as usual: |
38 | 26 |
|
39 | 27 | ``` js
|
40 | 28 | const router = new VueRouter({
|
41 | 29 | routes: [
|
42 |
| - { |
43 |
| - path: '/async', |
44 |
| - component: function (resolve) { |
45 |
| - require(['./MyComponent.vue'], resolve) |
46 |
| - } |
47 |
| - } |
| 30 | + { path: '/foo', component: Foo } |
48 | 31 | ]
|
49 | 32 | })
|
50 | 33 | ```
|
51 | 34 |
|
52 |
| -Now, `MyComponent.vue`, along with any dependencies that are only used by itself, |
53 |
| -will be loaded asynchronously only when the route `/async` needs to be rendered. |
54 |
| - |
55 |
| -### Browserify |
| 35 | +### Grouping Components in the Same Chunk |
56 | 36 |
|
57 |
| -TODO make this part as easy as wepack's |
58 |
| - |
59 |
| -It's a bit more tricky to achieve the same with Browserify, but it's possible |
60 |
| -with the |
61 |
| -[`partition-bundle` plugin](https://github.com/substack/browserify-handbook/blob/master/readme.markdown#partition-bundle). |
62 |
| -You will have to manually declare your bundle mappings in a `json` file: |
63 |
| - |
64 |
| -``` json |
65 |
| -{ |
66 |
| - "main.js": ["./main.js"], |
67 |
| - "my-component.js": ["./MyComponent.vue"] |
68 |
| -} |
69 |
| -``` |
70 |
| - |
71 |
| -Then in `main.js` you would do something similar, using the `loadjs` function instead of `require`: |
| 37 | +Sometimes we may want to group all the components nested under the same route into the same async chunk. To achieve that we need to use [named chunks](https://webpack.github.io/docs/code-splitting.html#named-chunks) by providing a chunk name to `require.ensure` as the 3rd argument: |
72 | 38 |
|
73 | 39 | ``` js
|
74 |
| -const router = new VueRouter({ |
75 |
| - routes: [ |
76 |
| - { |
77 |
| - path: '/async', |
78 |
| - component: function (resolve) { |
79 |
| - loadjs(['./MyComponent.vue'], resolve) |
80 |
| - } |
81 |
| - } |
82 |
| - ] |
83 |
| -}) |
| 40 | +const Foo = r => require.ensure([], () => r(require('./Foo.vue')), 'group-foo') |
| 41 | +const Bar = r => require.ensure([], () => r(require('./Bar.vue')), 'group-foo') |
| 42 | +const Baz = r => require.ensure([], () => r(require('./Baz.vue')), 'group-foo') |
84 | 43 | ```
|
| 44 | + |
| 45 | +Webpack will group any async module with the same chunk name into the same async chunk - this also means we don't need to explicitly list dependencies for `require.ensure` anymore (thus passing an empty array). |
0 commit comments