Dynamic import splits code but doesn't lazy load

1.3k Views Asked by At

I want to introduce lazy loading to Vue Router, so that some parts of the code will be loaded only on demand.

I'm following the official documentation for Lazy Loading in Vue Router: https://router.vuejs.org/en/advanced/lazy-loading.html

So for a test I've changed how the Vault module is imported in my router file:

import Vue from 'vue';
import Router from 'vue-router';

// Containers
import Full from '@/containers/Full';

// Views
// TODO: views should be imported dynamically
import Dashboard from '@/views/Dashboard';
const Vault = () => import('@/views/Vault');
import Page404 from '@/views/Page404';
import Page500 from '@/views/Page500';
import Login from '@/views/Login';

Vue.use(Router);

export default new Router({
    routes:         [
        {
            path:      '/',
            redirect:  '/dashboard',
            name:      'VENE',
            component: Full,
            children:  [
                {
                    path:      'dashboard',
                    name:      'dashboard',
                    component: Dashboard
                },
                {
                    path:      'vault',
                    name:      'vault',
                    component: Vault
                },
            ],
        },
        {
            path:      '/login',
            name:      'Login',
            component: Login,
        },
        {
            path:      '/404',
            name:      'Page404',
            component: Page404,
        },
        {
            path:      '/500',
            name:      'Page500',
            component: Page500,
        },
    ],
});

All fine, however, when I open the app for the first time, the extracted bundle which was supposed to be lazy loaded, is loaded up front:

enter image description here

When I go to that view using router it appears in Dev Tools Network Tab again, but says it's loaded from the disk, so the bundle is clearly loaded on first page load, which is totally against the idea of lazy loading.

1

There are 1 best solutions below

1
On

This is occurring for a couple reasons. I should say, you've set everything up correctly for lazy-loading the Vault component. One tip, I've found it helpful to add the webpack chunk name to the dynamic import:

const Vault = () => import(/* webpackChunkName: "vault" */ '@/views/Vault')

This would then show up in your network tab named with the chunkName "vault"

First, I'm guessing that you're using @vue-cli looking at your file structure and /src alias. Depending on the options you select when creating your project, @vue-cli uses a webpack config for progressive web apps that prefetches all resources. While the browser has mechanisms for prioritizing these downloads, I've found that some of the prefetching appears to block other resources. The benefit of prefetching is for browsers that don't support service-workers, you use idle browser time to put resources in the browser cache that the user will probably eventually use. When the user does need that resource, it is already cached and ready to go.

Second, you do have options for disabling the prefetch plugin. @vue-cli provides escape hatches for overriding the default config. Simply edit or add vue.config.js to the root of your project.

courtesy @LinusBorg 

// vue.config.js
chainWebpack: (config) => {

  // A, remove the plugin
  config.plugins.delete('prefetch')

  // or:
  // B. Alter settings:
  config.plugin('prefetch').tap(options => {
    options.fileBlackList.push([/myasyncRoute(.)+?\.js$/])
    return options
  })
}

-- Be sure to only use either option A or option B; not both. --

Source: https://github.com/vuejs/vue-cli/issues/979

I've used option A with success, but you should definitely benchmark the results yourself and go with the option that best serves your users and application.

I appreciate the configurability of @vue-cli for these and many scenarios. It's definitely worth exploring to write the application you want, rather than coercing your app to the config.