webpack5 代码分离

代码分离. 这一章的目的在于重用以及基本的缓存

首先第一部分在于提出公用的,比如都是 loadsh 是公用的部分。

如果正常发布的话,index.jsanother-module.js. 都会打包 loadsh.

index.js

import _ from 'lodash';

console.log(_.join(['index','loaded'], ' '));
<span class="copy-code-btn">复制代码</span>

another-module.js

import _ from 'lodash';

console.log(_.join(['Another', 'module', 'loaded!'], ' '));
<span class="copy-code-btn">复制代码</span>

01 代码分离的方法 主动选择分享哪些模块

entry: {
           index: {
              import: './src/index.js',
              dependOn: 'shared',
            },
            another: {
              import: './src/another-module.js',
              dependOn: 'shared',
            },
            shared: 'lodash'
}
<span class="copy-code-btn">复制代码</span>

shared 关键字可以例举出公共的模块。 在具体的路径中 dependOn 选择 shared.

就可以选择哪些依赖。shared 也可以是数组。 我想到另一种可能,我有多种 shared 模式有多种可能,于是我测试了一下。

entry: {
        index: {
            import: './src/index.js',
            dependOn: 'shared',
        },
        another: {
            import: './src/another-module.js',
            dependOn: ['shared', 'shared1'],
        },
        shared: 'lodash',
        shared1: 'moment'
}
<span class="copy-code-btn">复制代码</span>

这样也可以。

这样相对来说比较灵活。

只是文档中有一句我实在是不明白

如果我们要在一个 HTML 页面上使用多个入口时,还需设置 optimization.runtimeChunk: 'single',否则还会遇到这里所述的麻烦。

我查看了这个链接以后,理解了问题的意思。

就是不同的入口应该是重新实例化对象,来解决文章中文问题。

但是为什么加 optimization.runtimeChunk: 'single' 就能解决,我查了下含义

optimization.runtimeChunk 具体作用是什么?

其实就是解决缓存问题的,虽然我还没有做过实验,所以这里我并没有理解。

02 代码分离的方法 自动分离公共模块

回到最初的入口方式

    entry: {
      index: './src/index.js',
      another: './src/another-module.js',
    },
<span class="copy-code-btn">复制代码</span>

但是有办法能够自动分离,而不用选择

optimization: {
        splitChunks: {
            chunks: 'all'
        }
    }
<span class="copy-code-btn">复制代码</span>

就能自动将公共的模块分离出来,我查了下 splitChunks

SplitChunksPlugin

    splitChunks: {
      chunks: 'async',
      minSize: 20000,
      minRemainingSize: 0,
      minChunks: 1,
      maxAsyncRequests: 30,
      maxInitialRequests: 30,
      enforceSizeThreshold: 50000,
      cacheGroups: {
        defaultVendors: {
          test: /[\/]node_modules[\/]/,
          priority: -10,
          reuseExistingChunk: true,
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true,
        },
      },
    },
  },
<span class="copy-code-btn">复制代码</span>

我开始会担心,提取成一个公共 chunk 是否会太大,这些属性证明我想多了。

代码分离这件事,主要还是优化速度。你经常改变的是业务逻辑,公共组件其实很少变,提取出来,最大化利用浏览器缓存。

大概是这样子,具体属性可以等用到了再研究。

03 dynamic import

动态导入这个东西队伍贫乏的 webpack 知识,以前似乎也有类似的方法,能够实现动态加载和拆分模块,使用 jsonp 去动态加载,只是语法似乎和这个不太一样。

说起来也简单,首先我引入 moment , 然后写个方法动态加载。

dynamic.js

export default async () => {
    let { default: m } = await import("moment");
    let timeString = m().format('MMMM Do YYYY, h:mm:ss.SSS a');
    console.log("-----dynamicImport in test------");
    console.log(timeString);
    return timeString;
}
<span class="copy-code-btn">复制代码</span>

然后外部引用后,直接编译。

2607814-6458a9a1bd93f38d.png

moment 会有两个,一个语言包一个程序,一般正常是一个。

原理可以看这里 深入了解 webpack 模块加载原理

就是 jsonp 加载。

那么这时候还有另外一种用法,就是写在按钮事件里或者其他延时加载的方法。

   dynamicImportBtn.innerHTML = 'dynamic import btn';
   dynamicImportBtn.onclick = async () => {
        let { default: m } = await import("moment");
        let timeString = m().format('MMMM Do YYYY, h:mm:ss.SSS a');
        console.log("-----dynamicImport in test------");
        console.log(timeString);
    }
    element.append(dynamicImportBtn);
<span class="copy-code-btn">复制代码</span>

果然在点击按钮以后,才会加载对应 js.

04. 预加载

prefetch(预获取):将来某些导航下可能需要的资源 preload(预加载):当前导航下可能需要资源

<link rel="prefetch" as="script" href="http://127.0.0.1:5500/dist/762.bundle.js">
<link rel="prefetch" as="script" href="http://127.0.0.1:5500/dist/700.bundle.js">
<span class="copy-code-btn">复制代码</span>
<link rel="prefetch" as="script" href="http://127.0.0.1:5500/dist/762.bundle.js">
<link rel="prefetch" as="script" href="http://127.0.0.1:5500/dist/700.bundle.js">
<span class="copy-code-btn">复制代码</span>

在代码中的应用就是, 你提前加入这一段注释,告诉 webpack 你需要对这段代码执行什么策略

let { default: m } = await import(/* webpackPreload: true */ "moment");
<span class="copy-code-btn">复制代码</span>

最后会在html中生成, 但是需要注意的点是,前提你是通过 webpack 来生成 html

开始我以为这个是 webpck 通过 js 实现的,原来是 html 标准。

可以参考这两篇文章

www.webhek.com/post/link-p… www.cnblogs.com/cangqinglan…

总结来说就是

preload 并行下载 prefetch 闲时下载

自己估算好使用场景,选择预加载以及预加载的顺序

这里我不过多研究以及测试,后续需要用到之后在进行学习了测试

05. end

这一章主要还是为了教会我们如何使用 webpack 对代码进行分割。

给出了几种方式

  1. 提取公共代码,将公共代码单独提取,以便减小体积,也充分利用浏览器缓存。
  2. 拆分代码,不同逻辑的代码进行拆分,达到同样的效果
  3. 预加载,不管是图片也好,模块也好。预加载达到优化速度的请求

最后文中给出了几种分析包的方式,插件。

后续有机会实验一下。

webpack5 代码分离的相似文章

webpack 学习系列(二):你可能不知道 tree shaking分析webpack 之 LoaderRunner 全方位揭秘分析多图详解,一次性搞懂Webpack Loader分析