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.
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.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.