
Load Code on Demand Through Webpack, Extract Third-Party Libraries, Reduce Redundant Code When Converting ES6 to ES5
Load Code on Demand Through Webpack, Extract Third-Party Libraries, Reduce Redundant Code When Converting ES6 to ES5 관련
The following quote from the official Webpack documentation explains the concept of lazy loading:
Lazy Loading (webpack.docschina.org
)
"Lazy loading or on-demand loading is a great way to optimize a website or application. This approach actually separates your code at some logical breakpoints, and then immediately references or is about to reference some new code blocks after completing certain operations in some code blocks. This speeds up the initial loading of the application and lightens its overall volume because some code blocks may never be loaded."
Note
While image lazy loading (discussed in section 9.1) delays the loading of image resources until they're visible in the viewport, code lazy loading splits JavaScript bundles and loads code fragments only when they're needed for specific functionality. They both improve initial load time, but they work at different levels of resource optimization.
Generate File Names Based on File Content, Combined with Import Dynamic Import of Components to Achieve On-Demand Loading
This requirement can be achieved by configuring the filename property of output. One of the value options in the filename property is [contenthash]
, which creates a unique hash based on file content. When the file content changes, [contenthash]
also changes.
output: {
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].js',
path: path.resolve(__dirname, '../dist'),
},
Example of code lazy loading in a Vue application:
// Instead of importing synchronously like this:
// import UserProfile from './components/UserProfile.vue'
// Use dynamic import for route components:
const UserProfile = () => import('./components/UserProfile.vue')
// Then use it in your routes
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: UserProfile }
]
})
This ensures the UserProfile
component is only loaded when a user navigates to that route, not on initial page load.
Extract Third-Party Libraries
Since imported third-party libraries are generally stable and don't change frequently, extracting them separately as long-term caches is a better choice. This requires using the cacheGroups option of Webpack4's splitChunk plugin.
optimization: {
runtimeChunk: {
name: 'manifest' // Split webpack's runtime code into a separate chunk.
},
splitChunks: {
cacheGroups: {
vendor: {
name: 'chunk-vendors',
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: 'chunk-common',
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
},
}
},
test
: Used to control which modules are matched by this cache group. If passed unchanged, it defaults to select all modules. Types of values that can be passed:RegExp
,String
, andFunction
.priority
: Indicates extraction weight, with higher numbers indicating higher priority. Since a module might meet the conditions of multiplecacheGroups
, extraction is determined by the highest weight.reuseExistingChunk
: Indicates whether to use existing chunks. If true, it means that if the current chunk contains modules that have already been extracted, new ones won't be generated.minChunks
(default is 1): The minimum number of times this code block should be referenced before splitting (note: to ensure code block reusability, the default strategy doesn't require multiple references to be split).chunks
(default is async): initial, async, and all.name
(name of the packaged chunks): String or function (functions can customize names based on conditions).
Reduce Redundant Code When Converting ES6 to ES5
To achieve the same functionality as the original code after Babel conversion, some helper functions are needed. For example this:
class Person {}
will be converted to this:
"use strict";
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var Person = function Person() {
_classCallCheck(this, Person);
};
Here, _classCallCheck
is a helper
function. If classes are declared in many files, then many such helper
functions will be generated.
The @babel/runtime
package declares all the helper functions needed, and the role of @babel/plugin-transform-runtime
is to import all files that need helper
functions from the @babel/runtime package
:
"use strict";
var _classCallCheck2 = require("@babel/runtime/helpers/classCallCheck");
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj };
}
var Person = function Person() {
(0, _classCallCheck3.default)(this, Person);
};
Here, the helper
function classCallCheck
is no longer compiled, but instead references helpers/classCallCheck
from @babel/runtime
.
Installation:
npm i -D @babel/plugin-transform-runtime @babel/runtime
Usage:
In the .babelrc
file,
"plugins": [
"@babel/plugin-transform-runtime"
]