laravel mix - lazy loading Vue components



why?

Lazy loading components gives a great performance improvement. Larger components can take ages to load and result in an unusable page for a few seconds while the massive app.js file is loaded.

how?

You can follow these steps on the tutorial repo .

1. babel plugins

You will need to add both the babel-plugin-dynamic-import-webpack and babel-plugin-syntax-dynamic-import packages to your package.json

$ npm install --save-dev \ 
    babel-plugin-dynamic-import-webpack \
    babel-plugin-syntax-dynamic-import

tutorial commit

2. bable config

Create a file in the root of your Laravel application called .babelrc with the following contents.

{
    "plugins": ["syntax-dynamic-import"]
}

tutorial commit

3. webpack config

Update your webpack.mix.js file to the following:

let mix = require('laravel-mix');

// Override mix internal webpack output configuration
mix.config.webpackConfig.output = {
    chunkFilename: 'js/[name].bundle.js',
    publicPath: '/',
};

mix.js('resources/assets/js/app.js', 'public/js')
   .sass('resources/assets/sass/app.scss', 'public/css')
   .version(); 

tutorial commit

4. app.js

Instead of loading components in the standard way,

Vue.component(
    'example-component',
    require('./components/ExampleComponent.vue') 
);

We need to use the lazy loading import method.

Vue.component(
    'example-component', 
    () => import(
        /* webpackChunkName: "example-component" */
        './components/ExampleComponent.vue'
    )
);

The import() function will load the Vue component in dynamically, so it is only loaded by the browser when actually used.

/* webpackChunkName: "example-component" */ is used to specify the name of the bundle file webpack generates. In this instance a file called example-component.bundle.js is created in the public/js/ directory.

tutorial commit

5. done

Now you have lazy loading components, your application will be a little more responsive on first load and when each Vue component initialises, the browser will load the component’s file chunk.

a note on sub-components

Sub-components will be included in the bundle of the parent component they are imported into.

Say we add a new component to ExampleComponent.vue

import ExampleSubComponent from './ExampleSubComponent.vue'; 

export default {   
    components: {    
        ExampleSubComponent,
    },   
    mounted() {
        console.log('Component mounted.')   
    } 
};

The ExampleSubComponent will be included in public/js/example-component.bundle.js rather than public/js/app.js.