webpacak5 代码分离

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

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

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

index.js

import _ from 'lodash';

console.log(_.join(['index','loaded'], ' '));

another-module.js

import _ from 'lodash';

console.log(_.join(['Another', 'module', 'loaded!'], ' '));

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

entry: {
           index: {
              import: './src/index.js',
              dependOn: 'shared',
            },
            another: {
              import: './src/another-module.js',
              dependOn: 'shared',
            },
            shared: 'lodash'
}

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'
}

这样也可以。

这样相对来说比较灵活。

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

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

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

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

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

optimization.runtimeChunk 具体作用是什么?

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

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

回到最初的入口方式

    entry: {
      index: './src/index.js',
      another: './src/another-module.js',
    },

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

optimization: {
        splitChunks: {
            chunks: 'all'
        }
    }

就能自动将公共的模块分离出来,我查了下 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,
        },
      },
    },
  },

我开始会担心,提取成一个公共 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;
}

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

图片.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);

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

04. 预加载

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





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

let { default: m } = await import(/* webpackPreload: true */ "moment");

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

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

可以参考这两篇文章

https://www.webhek.com/post/link-prefetch.html
https://www.cnblogs.com/cangqinglang/p/11308243.html

总结来说就是

preload 并行下载
prefetch 闲时下载

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

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

05. end

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

给出了几种方式

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

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

后续有机会实验一下。

你可能感兴趣的:(webpacak5 代码分离)