The separation

Code separation is the most important feature of WebPack, separating code into different bundles to facilitate on-demand or parallel loading of resources, which affects load time. Common code segmentation methods:

  • Entry point: UseentryConfigure manual separation of code
  • Prevent repetition: useEntry dependenciedorSplitChunksPluginDeweighting and separationchunk.
  • Dynamic import: Separation of code through inline function calls to modules.

Entrance to the starting point

  • index.js
import _ from 'lodash'
import { add } from './a.js'
function component() {
    const element = document.createElement('div');
  
    // Lodash (currently introduced as a script) is required to perform this line
    element.innerHTML = _.join(['Hello'.'webpack'].' ');
  
    return element;
  }
  console.log(add(2.5))
  document.body.appendChild(component());
Copy the code
  • another-module.js
import _ from 'lodash';

console.log(_.join(['Another'.'module'.'loaded! '].' '));
Copy the code
  • webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
  mode: 'development'.entry: {
    index:'./src/index.js'.1 / / entry
    Another:'./src/another-module.js'.2 / / entry
  },
  devtool: 'inline-source-map'.// The error module information can be accurately located here (sourcemap)
  plugins: [new CleanWebpackPlugin(),
      new HtmlWebpackPlugin({
          title:'Manage output'})].output: {
    filename: '[name].main.js'.path: path.resolve(__dirname, 'dist'),}};Copy the code

There are some pitfalls in the above methods:

  • If the entry chunks contain duplicate modules, those duplicate modules will be introduced into different bundles.
  • At the same time, the core application cannot be dynamically separated from the code in this way

The first of these is easy to see. We introduced LoDash in index.js, but we need to re-introduce it in another- module-js.

To prevent the repeat

By configuring the dependOn option in the file, modules can be shared between multiple chunks. Reduce the size of the module code by extracting common dependencies between the two files and generating separate module files at packaging time. If we want to use multiple entry on an HTML page, still need to set up optimization. RuntimeChunk: ‘single’

  • webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
  mode: 'development'.entry: {
    index: {
      import: './src/index.js'.dependOn: 'shared',},another: {
      import: './src/another-module.js'.dependOn: 'shared',},shared: 'lodash',},devtool: 'inline-source-map'.// The error module information can be accurately located here (sourcemap)
  plugins: [new CleanWebpackPlugin(),
      new HtmlWebpackPlugin({
          title:'Manage output'})].output: {
    filename: '[name].main.js'.path: path.resolve(__dirname, 'dist'),},optimization: {
    runtimeChunk: 'single',}};Copy the code

Dynamic code import

Webpack uses two similar approaches when it comes to dynamic code splitting.

  • 1. Use the import syntax for dynamic imports, and the packaged code automatically packages the dynamically imported packages as a vendors. You do not need to configure it.
  import('lodash').then(_= > {
    // Do something with lodash (a.k.a '_')...
  });
Copy the code
  • 2. Use WebPack specificrequire.ensure
 require.ensure(['b'].function(require) {
    var c = require('c');

    // Do something special...
  });
Copy the code

Prefetch/Preload module (Prefetch/Preload)

Implementation with import

function button(){
  const ele = document.createElement('button')
  ele.innerHTML = 'button'
  ele.onclick = function(){
    import(/* webpackPrefetch: true */ './a').then(res= >{
      console.log(res)
    })
  }
  return ele
}
Copy the code

The directive configuration is generated<link rel="prefetch" as="script" href="src_a_js.main.js"></head>It is appended to the page header to indicate the browser idle time prefetchsrc_a_js.main.jsFile. You can also view the resource obtaining method on the Performance pagePreload differs in some ways from the prefetch directive:

  • Preload Chunk is loaded in parallel when the parent chunk is loaded. Prefetch Chunk is loaded after the parent chunk is loaded.
  • Preload Chunks have a medium priority and are downloaded immediately, while Prefetch Chunks are downloaded when the browser is idle.
  • Preload Chunk is requested immediately in the parent component for the present moment. Prefetch Chunk will be used at some point in the future.
  • Browser support for Prefetch is about 70% and for Preload is about 50%

The cache

Getting resources from the server from the browser is usually time consuming. Browsers hit caches to reduce network traffic and make websites load faster, but if the file name of the resource is not changed at deployment time, the browser may assume that it is not updated and will use its cached version.

filename

When contenthash is configured in output.filename, a unique hash will be created based on the content of the resource. When the content of the resource changes, [contenthash] will also change, and the filename will contain a unique hash value in the packaged file.

Extracting the boot Template

In code separation, splitChunkSplugin can be used to separate modules into separate bundles. Can use optimization. RuntimeChunk option to the runtime code into a separate chunk. Set it to Single to create a Runtime bundle for all chunks

Asset vendors - node_modules_lodash_lodash_js. 0120508 cd546f3f22c19. Js 1.37 MiB [emitted] [immutable] (id hint: Vendors) asset runtime. C84f401aa9ba9c916849. Js 34.1 KiB [emitted] [immutable] (name: The runtime) asset index. E429b554c829d01de78b. Js 3.47 KiB [emitted] [immutable] (name: index) asset src_a_js.eded08a4d8cac1861aca.js 939 bytes [emitted] [immutable] asset index.html 303 bytes [emitted] Entrypoint index KiB = 37.6 runtime. C84f401aa9ba9c916849. Js 34.1 KiB index. E429b554c829d01de78b. Js KiB 3.47 runtime Modules 9.86 KiB 13 modulesCopy the code

Usually, third-party libraries such as Lodash, Vue and React are extracted into separate Vendor Chunk files. Since they are rarely changed, the caching mechanism of sci-fi segment can be used to eliminate requests by hitting the cache and reduce resource acquisition from the server, while ensuring the accuracy of the code. This can be done by using the cacheGroups option of the SplitChunksPlugin plug-in. We add the cacheGroups parameter to optimization.splitchunks and build:

  • Add:
Asset vendors - node_modules_lodash_lodash_js. 0120508 cd546f3f22c19. Js 1.37 MiB [emitted] [immutable] (id hint: Vendors) asset runtime. C84f401aa9ba9c916849. Js 34.1 KiB [emitted] [immutable] (name: The runtime) asset index. C8aef78ae031df99c50e. Js 5.85 KiB [emitted] [immutable] (name: index) asset src_a_js.eded08a4d8cac1861aca.js 939 bytes [emitted] [immutable] asset index.html 303 bytes [emitted] Entrypoint index KiB = 40 runtime. C84f401aa9ba9c916849. Js 34.1 KiB index. C8aef78ae031df99c50e. 5.85 KiB jsCopy the code
  • After adding:
Asset vendorstest. A477574b3560f21a228f. Js 1.37 MiB [emitted] [immutable] (name: vendorstest) (id hint: Vendor) asset runtime. 2 bba52c28f516bccc037. Js 33.9 KiB [emitted] [immutable] (name: The runtime) asset index. 2 dfd9b3c84a3ec76ba9e. Js 3.86 KiB [emitted] [immutable] (name: index) asset src_a_js.eded08a4d8cac1861aca.js 939 bytes [emitted] [immutable] asset index.html 362 bytes [emitted] Entrypoint index MiB = 1.41 runtime. 2 bba52c28f516bccc037. Js 33.9 KiB vendorstest. A477574b3560f21a228f. Js 1.37 MiB 3.86 KiB index. 2 dfd9b3c84a3ec76ba9e. JsCopy the code

The index file size is 5.85 KB before and 3.56 KB after the code optimization.

Lazy loading

Lazy load or load on demand, can be a good optimization of the page. This is essentially breaking off some logical breakpoints and then doing something in some code block. This speeds up the loading of the application and reduces mention, as some code blocks may never be loaded.

conclusion

Webpack optimization
  • 1. Set a hash value for the module file name for cache matching and update.
  • 2. Remove modules from node_modules. Node_modules usually change very little during development, so you can take advantage of the browser cache to reduce requests.
  • 3. Use runtimeChunk to extract the main code at runtime

Reference Documents:

  • Webpack.docschina.org/blog/2020-1…
  • Webpack.docschina.org/guides/code…
  • Webpack.docschina.org/guides/deve…
  • Blog.fundebug.com/2019/04/11/…