Lazy code loading
This is the 10th day of my participation in the August More Text Challenge. For details, see:August is more challenging
One of the most commonly used scenarios for dynamic import is lazy loading (such as route lazy loading)
For example, lazy loading can be used when we want to render something on the page after clicking a button
element.js
const divElem = document.createElement('div')
divElem.innerHTML = 'hello world'
export default divElem
Copy the code
index.js
const btn = document.createElement('button')
btn.innerHTML = 'click me'
document.body.appendChild(btn)
btn.addEventListener('click'.() = > {
// Simple implementation of lazy loading
import('./element').then(({default: element}) = > document.body.appendChild(element))
})
Copy the code
Prefetch and Preload
The previous lazy loading case has a point that can be optimized:
By default, after we click the button, the browser downloads the script and then loads and parses the corresponding script
Now, if the script is large, it might not give the user a very good idea,
So we can download these scripts in advance at the right time
At execution time, you simply load and parse the corresponding script
Starting with Webpack V4.6.0 +, WebPack has added support for prefetch and preload
configuration | instructions |
---|---|
prefetch(Pre-acquired) | Wait for the browser needs to load the resources loaded, the browser idle, to the corresponding resources to pre-download down Typically used to display resources that may be needed under some future navigation |
preload(Preloading) | Along with the parent chunk(the file in which the current import is located)parallel downloadTypically used to display resources that may be required under the current navigation |
btn.addEventListener('click'.() = > {
// The preload and Prefetch functions are enabled using magic comments. Multiple magic comments can be configured at the same time
Set preload and prefetch to true
import(
/* webpackPrefetch: true */
/* webpackChunkName: 'element' */
'./element'
).then(({default: element}) = > document.body.appendChild(element))
})
Copy the code
runtimeChunk
To configure whether runtime related code is extracted into a separate chunk:
Runtime code refers to the code that parses, loads, and relates to module information in the runtime environment
That is, code that we didn’t write, but that was necessary at runtime, and that was added to us by WebPack
At this point, we can pull out the runtime code
So that when we change the business code, the Runtime code does not need to be reloaded
value | instructions |
---|---|
The default value | Runtime does not perform separate extraction operations |
true/multiple | Package a Runtime file for each entry and generate runtime~${entryPoint. Name} files for each entry |
single | Package a Runtime file |
object | The name attribute determines the name of runtimeChunk |
optimization: {
runtimeChunk: {
// The resulting file is spliced with runtimechunk.name and output.filename, such as foo.bundle.js
name: 'runtime'}}Copy the code
optimization: {
runtimeChunk: {
// entryPoint is an object
// This object has an attribute name whose value is the name of the entry name in the entry
name: (entryPoint) = > {
return `runtime~${entryPoint.name}`}}}Copy the code
In principle, it is not recommended to split runtime into multiple packages for parsing, because the JS files will eventually be imported in a certain order in index.html.
This means that objects exposed in the Runtime are set to global objects. If you split them into multiple Runtime objects, you will have global variable contamination.
An object of the same name in the later Runtime overwrites an object of the same name in the previous Runtime. For example, every Runtime may have a __webPack__require__ object
CDN
A CDN is called a Content Delivery Network or Content Distribution Network.
- It refers to using the server closest to each user through an interconnected network system
- Faster and more reliable delivery of music, photos, videos, apps, and other files to users
- To provide high performance, scalability and low cost network content delivery to users
When a user requests a resource, it will go to the server nearest to the user (edge node) to request the resource
If the resource exists, download it directly. If the resource does not exist, go to the parent node of the edge node to find it.
And so on, find direct return, no find continue to go to the node’s parent node to find, until find the source (source node)
When resources are delivered, each node server will cache the corresponding resources on this node
In this way, when the next user needs to access the same resource, the user can return the required resource through the node closest to the user.
In development, we use CDN in two main ways
- All static resources are packaged and put into the CDN server. All user resources are loaded through the CDN server
- Its own business code is stored on its own server, and some third-party resources are put on the CDN server
Place them all on the CDN server
If we want to put all our static resources on a CDN server, we need to buy our own CDN server
At present, Alibaba, Tencent, Amazon, Google and so on can buy CDN servers
output: {
path: path.resolve(__dirname, '.. /dist'),
filename: '[name].bundle.js'.// Set the CDN path to publicPath. All resources will be automatically added to this path when they are packaged
publicPath: 'https://www.example.com/cdn'
},
Copy the code
Only third parties are placed on the CDN server
Usually some of the better known open source frameworks will package the source code to some of the better known, free CDN servers
The international use is more unPkg, JSDelivr, CDNJS
There is also a more useful CDN is BOOTCDN
webpack.config.js
module.exports = {
// Externals is the top-level configuration option for WebPack
externals: {
// key ===> Module name
// value ===> The object exposed by the module
'dayjs': 'dayjs'.'lodash': '_'}}Copy the code
index.html
<body>
<! Because all third-party libraries are not packaged into the source code, you need to set up the CDN links for all third-party libraries in the HTML -->
<script src="https://unpkg.com/[email protected]/dayjs.min.js"></script>
<script src="https://unpkg.com/[email protected]/lodash.js"></script>
</body>
Copy the code
At the time of development, our server and browser are both local, so there is no need to set third-party packages to the CDN, because this can be done multiple times
At this point we can use EJS to determine the development environment for our HTML template
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta Name ="viewport" content="width=device-width, initial-scale=1.0"> <title>Webpack</title> <body> <! Process.env.node_env === 'production'){%> <script (process.env.node_env === 'production') SRC = "https://unpkg.com/[email protected]/dayjs.min.js" > < / script > < script SRC = "https://unpkg.com/[email protected]/lodash.js" > < / script > < %} % > < / body > < / HTML >Copy the code
Pull out the CSS code
The MiniCssExtractPlugin helps us extract the CSS into a separate CSS file
This plug-in is intended for use in production environments, but development environments are optional
#The installation
npm install mini-css-extract-plugin -D
Copy the code
configuration
config.common.js
const miniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = env= > {
const commonConfig = env= > ({
module: {
rules: [{test: /\.css$/,
use: [
// The development environment uses styleloader, and the production environment uses miniCssExtractPlugin
env.production ? miniCssExtractPlugin.loader : 'style-loader'.'css-loader']}]}})return env.production ? merge(commonConfig(env), prodConfig) : merge(commonConfig(env), devConfig)
}
Copy the code
config.prod.js
const miniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
plugins: [
new miniCssExtractPlugin({
// There is no placeholder named ext because the style is pulled away
filename: 'css/[name].[hash:6].css'}})]Copy the code
The value of env
Env is a very special object in Node. All values in env are converted to strings before being stored
This is node’s special treatment of env objects, which does not exist in any other Node objects
In webpack.config.js, if you need to store values in process.env, you need to pay attention and handle them accordingly
const un = undefined
const num = 123
process.env.un = un
process.env.num = num
console.log(process.env.un, typeof process.env.un) // => undefined string
console.log(process.env.num, typeof process.env.num) // => 123 string
Copy the code