Introduce webpck5
Webpack5 has been out for more than a year and is still in the beta stage. It can be installed and used now
installation
```
npm install webpack@next webpack-cli -D
yarn add webpack@next webpack-cli -D
```
Copy the code
HTML plug-ins are COMPATIBLE with HTML
- You need to
html-webpack-plugin
Upgrade to version 4.3.0
Environmental requirements
- The latest official documentation requires node to be at least version 10.13.0
New Features
- Persistent cache
- ModuleIds & chunkIds optimization
- More intelligent Tree shaking
- NodeJs’s polyfill script has been removed
- Support to generate e6/ ES2015 code
- SplitChunk and module size
- Module Federation
Experience with
- After hands-on use, webpack5 has improved its package size, continuous compilation speed and compatibility with webpack4. Module Federation also provides a solution for using micro-front-end applications in projects. If incompatibilities occur during the upgrade, refer to the Webpack5 change log.
Persistent cache
- Before webpack5, it was available
cache-loader
Write the compiled structure to the hard disk cache, you can also usebabel-loader
To set upoption.cacheDirectory
willbabel-loader
The compiled results are written to disk. - In webpack5, caching is enabled by default, and caching is in memory by default. You can set the cache
module.export={
cache{
type:'filesystem', / /'memory' | 'filesystem'
cacheDirectory: 'node_modules/.cache/webpack'// By default, the cache is stored in node_modules/. Cache /webpack // cache dependencies. When the cache dependencies change, the cache fails. [__filename] } } }Copy the code
-
By default webpack assumes that the node_modules directory it is in is only modified by the package manager, skips hash and timestamp processing, and just uses the name and version of the package for performance reasons.
-
When cache.type: “filesystem” is set, webpack internally enables filesystem caching and memory caching in a hierarchical manner. When reading from the cache, the memory cache is first looked at, and if it is not found, it is demoted to the file system cache. The write cache writes to both the memory cache and the file system cache.
-
The file system cache does not serialize requests to disk directly. It will not execute until the compilation process is complete and the compiler is idle. The reason for this is that serialization and disk writes take up resources, and we don’t want to delay the compilation process any further.
-
Cache elimination strategy design: The file cache is stored in node_modules/. Cache /webpack. For a cache set, the maximum number of cache contents should not exceed 5, and the maximum cumulative resource usage should not exceed 500MB. The cache is also designed to be valid for two weeks.
ModuleIds & chunkIds optimization
The chunk and the module
- Chunk: Webpack packs individual file blocks that are eventually generated. Each file corresponds to a chunk.
- Module: Each source JS file can be viewed as a module.
The disadvantage of chunkId
- Webpack5 improved
moduleIds
和chunkIds
Sure. Before webpack5, there was no slaveentry
The chunk files are packaged in a 1,2,3… File naming method output. (The hash value after the file name is generated with chunkhash)
- Js ->1.js, 3.js->2.js, and this will invalidate the cache of 2.js requests that were originally online.
- This was also possible before webpack5
webpackChunkName
To solve the naming problem
. <Switch> <Route key='/' exact path='/' component={
Loadable({
loader: () => import(/* webpackChunkName: "home"* /'./home'),
loading: (<div>loadding</div>)
})
}/>
<Route key='/page1' exact path='/page1' component={
Loadable({
loader: () => import(/* webpackChunkName: "page1"* /'./page1'),
loading: () => (<div>loadding</div>)
})
} />
<Route key='/page2' exact path='/page2' component={
Loadable({
loader: () => import(/* webpackChunkName: "page2"* /'./page2'),
loading: () => (<div>loadding</div>)
})
} />
</Switch>
....
Copy the code
- This seems to solve the cache invalidation problem, but when we open the compiled home.js, chunkId is still there. If the home menu is deleted, the chunkId of page1 and Page2 will still be changed.
- Page1.js is a packaged file
- File page1.js packed after removing home.js
- Even though page1.js has not been modified, the chunkhashi of page1.js will still change due to the change in chunkId caused by the deletion of home.js, and the problem of cache invalidity still exists.
The improvement of webapck5
- With the new algorithm, these features are enabled by default in production mode
chunkIds: "deterministic", moduleIds: "deterministic"
. - This algorithm assigns short numeric ids (3 or 4 characters) to Modules and chunks in a deterministic manner. This is a compromise between bundle size and long-term caching.
Optimization. moduleIds: Optional value: 1.falseTell WebPack not to use any built-in algorithms and provide custom algorithms through plug-ins. 2. 4. Deterministic generates short messages based on module nameshashValue 5.size Specifies the numerical ID generated based on the size of the module.falseTell WebPack not to use any built-in algorithms and provide custom algorithms through plug-ins. 2. 4. Deterministic generates short messages based on module nameshashValue 5.size The id calculated based on the size of the requested initial resource 6.. Total-size: specifies the ID calculated based on the size of the requested parsing resourceCopy the code
More intelligent Tree shaking
- Tree Shaking is enabled in the same way as WebPack4, using ES6 modularization and enabling the Production environment
- example
// a.js
export const a =22;
export const b = 33;
// b.js
import * as a from './a.js'
export {a};
// index.js
import * as b from './b.js'Console. log(B.A.A) // Outputs 22Copy the code
- Webpack4: When packaging, it will put
const b =33
Pack it in
- Webpack5: the packaged code is more streamlined
NodeJs’s polyfill script has been removed
- Webpack <= 4 comes with polyfil for many Node.js core modules, which are automatically enabled once any core modules are used in the module (i.e., “crypto” modules).
- While this makes it easy to write modules for Node.js, it adds oversized polyfills to the package. In many cases, these polyfills are not necessary.
import CryptoJS from 'crypto-js';
console.log(CryptoJS.MD5('123123'));
Copy the code
- Webpack4:
- Webpack5:
Support to generate e6/ ES2015 code
- Webpack5 adds ecmaVersion to Output
output: { ecmaVersion: 6 }
The code generated by default compilation in WebPack corresponds to the ES5 version. - There are two Settings:
5 =< ecmaVersion <= 11
2009 =< ecmaVersion <= 2020
SplitChunk and module size
- Modules are now able to represent sizes in a better way than displaying single numbers and different types of sizes.
- By default, only javascript sizes can be handled, but you can now pass multiple values to manage them:
optimization{
splitChunks{
minSize: {
javascript: 30000,
style: 50000,
}
}
}
Copy the code
Module Federation
- Module Federation enables JavaScript applications to load code dynamically from another JavaScript application — while sharing dependencies. Let code be shared directly between projects using CDN, no need to install Npm package locally, build and distribute!
- Dynamic loading allows code to load another application’s code at run time on demand.
- Example: Reference a button component exposed in App2 in App1
// app1 - webpack.config.js
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
//....
plugins: [
new ModuleFederationPlugin({
name: "app1"// library: {type: "var", name: "app1"}, remotes: {// Need to reference the remote application, as in app2 library name field app2"app2",
},
shared: ["react"."react-dom"}),],};Copy the code
// app2 - webpack.config.js
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
//....
plugins: [
new ModuleFederationPlugin({
name: "app2"// library: {type: "var", name: "app2"}, // UMD standard export, same as name. filename:"remoteEntry.js", the exposed chunkname exposes: {module to be exposed"./Button": "./src/Button",
},
shared: ["react"."react-dom"], the dependency shared with APP1. If app1 has one, the dependency in APP1 will be used preferentially. }),],};Copy the code
// app1/index.html // import app2 exposed files... <head> <srcipt src="http://localhost:3002/remoteEntry.js"></script>
</head>
...
app1/app.js
import AppTwoButton from 'app/Button';
const App = ()=>{
return (
<AppTwoButton/>
)
}
app1/bootstrap.js
ReactDOM.render(<App />, document.getElementById("root"));
app1/bootstrap.js
import("./bootstrap");
Copy the code
- Learn about Module Federation from the loading process
- App2 / remoteentry. js: app2/ remoteentry. js: app2/ remoteentry. js
- Load app1’s packaged main.js and go to bootstrap.js to find the dependency front and analyze it
- Then load the react.js file in main.js and the react-dom, which depends on prop-types.js
- Then when I went through Remote, I found that I depended on app2’s Button component
- After all dependencies of bootstrap.js are loaded, asynchronous loading is completed, then logic is executed to start the application
conclusion
- Module Federation provides new ideas for microfronts, code segmentation, shared dependencies, on-demand loading, and runtime loading. Disadvantages include sharing global variables and global styles, and not being elegant enough to expose modules to global variables.
- Webpackage 5 is still in the process of merging the code, the current version of Bate22, WebPackage 5 official release, we believe that Module Federation will continue to improve. All in all, webpack5 upgrade has a nice increase in build speed and package size.
The resources
- 1. The three application scenario research, Webpack new function Module Federation in-depth analytic: developer.aliyun.com/article/755…
- 2.Webpack5 hands-on reviews juejin.cn/post/684490…