Frontend Development 13 min read

Understanding Webpack Asynchronous Loading and Code Splitting Strategies

This article explains how Webpack's asynchronous loading mechanisms such as require.ensure and dynamic import() work, demonstrates practical examples for splitting bundles, discusses route lazy‑loading in Vue, and provides optimization techniques including splitChunks, CDN externals, and bundle analysis to improve frontend performance.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Understanding Webpack Asynchronous Loading and Code Splitting Strategies

Webpack can split JavaScript modules into separate files and load them on demand, a technique often called asynchronous loading or code splitting. By creating a script element and appending it to document.head , the browser fetches the module only when needed.

Basic Example

The entry file main.js depends on A.js and B.js , which should be loaded after clicking buttons aBtn and bBtn . The following webpack.config.js config bundles the entry:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  entry: { index: path.join(__dirname, '/src/main.js') },
  output: {
    path: path.join(__dirname, '/dist'),
    filename: 'index.js',
  },
  plugins: [
    new HtmlWebpackPlugin({ template: path.join(__dirname, '/index.html') }),
    new CleanWebpackPlugin(),
  ],
};

The corresponding index.html contains two buttons that trigger the loading of A.js and B.js :

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>webpack</title>
  </head>
  <body>
    <div id="app">
      <button id="aBtn">按钮A</button>
      <button id="bBtn">按钮B</button>
    </div>
  </body>
</html>

The modules themselves are simple:

// A.js
const A = 'hello A';
module.exports = A;

// B.js
const B = 'hello B';
module.exports = B;

require.ensure Asynchronous Loading

Using require.ensure , the two modules are split into separate chunks ( 1.index.js and 2.index.js ) that are loaded only when the corresponding button is clicked:

document.getElementById('aBtn').onclick = function () {
  // async load A
  require.ensure([], function () {
    let A = require('./A.js');
    alert(A);
  });
};

document.getElementById('bBtn').onclick = function () {
  // async load B
  require.ensure([], function () {
    let B = require('./B.js');
    alert(B);
  });
};

The generated chunk code is stored in the global webpackJsonp array and executed when the chunk is requested.

Dynamic import()

Webpack 4 supports the ES‑module import() syntax, which returns a Promise. The same lazy‑loading effect can be achieved with a more modern syntax:

document.getElementById('aBtn').onclick = function () {
  import('./A').then(data => alert(data.A));
};

document.getElementById('bBtn').onclick = function () {
  import('./B').then(data => alert(data.B));
};

Route Lazy‑Loading in Vue

Vue applications can lazy‑load routes using three approaches: Vue async components, require.ensure , and the ES6 import() function. Example with require.ensure :

export default new Router({
  routes: [
    {
      path: '/home',
      component: (resolve) => require.ensure([], () => resolve(require('@/components/home')),'home'),
    },
    {
      path: '/about',
      component: (resolve) => require.ensure([], () => resolve(require('@/components/about')),'about'),
    },
  ],
});

Webpack Split‑Chunk Strategy

Before Webpack 4, CommonsChunkPlugin was used to extract shared modules. In Webpack 4+, optimization.splitChunks replaces it and automatically creates vendor and common chunks when mode is set to production . Custom cache groups can further split large libraries such as echarts and iview :

chainWebpack: config => {
  config.optimization.splitChunks({
    chunks: 'all',
    cacheGroups: {
      vendors: { name: 'chunk-vendors', test: /[\/]node_modules[\/]/, priority: 10, chunks: 'initial' },
      iview: { name: 'chunk-iview', priority: 20, test: /[\/]node_modules[\/]_?iview(.*)/ },
      echarts: { name: 'chunk-echarts', priority: 20, test: /[\/]node_modules[\/]_?echarts(.*)/ },
      commons: { name: 'chunk-commons', minChunks: 2, priority: 5, chunks: 'initial', reuseExistingChunk: true },
    },
  });
},

Using CDN and Externals

Even after splitting, large third‑party libraries still increase load time. By loading them from a CDN and declaring them as externals in vue.config.js , the bundles become much smaller:

configureWebpack: config => {
  config.externals = {
    vue: 'Vue',
    xlsx: 'XLSX',
    iview: 'iView',
    iView: 'ViewUI',
  };
};

Corresponding CDN links are added to index.html head and body sections.

By combining code splitting, route lazy‑loading, splitChunks configuration, and CDN externals, the final bundle size can be reduced dramatically, eliminating massive vendor.js files and improving first‑paint performance for large Vue admin‑panel projects.

webpackCode SplittingAsync Loadingfrontend performanceImportrequire.ensureVue lazy loading
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.