webpack5 新特性

1:剔除npm包里面针对Node.js模块自动引用的Polyfills

v4编译引入npm包,有些npm包里面包含针对nodejs的polyfills,实际前端浏览器是不需要的
例如:

// index.js
import CryptoJS from 'crypto-js';
const md5Password = CryptoJS.MD5('123123');
console.log(md5Password);

v4 引入crypto-js模块会自动引入polyfill: crypto-browserify, 但部分代码是不需要的,v5 默认会自动剔除
v5编译中,会出现polyfill添加提示,如果不需要node polyfille,按照提示 alias 设置为 false 即可

// webpack.config.js
  resolve: {
    // 1.不需要node polyfilss
    alias: {
      crypto: false
    },
    // 2.手动添加polyfills
    // fallback: {
    //   "crypto": require.resolve('crypto-browserify')
    // }
  }

2:长期缓存优化,

以前v4是根据代码的结构生成chunkhash,现在v5根据完全内容生成chunkhash,比如改了内容的注释或者变量则不会引起chunkhash的变化,让浏览器继续使用缓存
1:moduleId改为根据上下文模块路径计算,chunkId根据chunk内容计算
2: 为module,chunk 分配确定的(3或5位)数字ID,这是包大小和长期缓存之间的一种权衡

3:持久化缓存

1:第一次构建是一次全量构建,它会利用磁盘模块缓存(以空间换时间),使得后续的构建从中获利。
2:后续构建具体流程是:读取磁盘缓存 -> 校验模块 -> 解封模块内容。

v5 默认情况,缓存配置是memory,修改设置为filesystem, 将缓存写入硬盘

// webpack.config.js
module.exports = { 
  cache: {
    // 1. 将缓存类型设置为文件系统
    type: 'filesystem', // 默认是memory
    // 2. 将缓存文件夹命名为 .temp_cache,
    // 默认路径是 node_modules/.cache/webpack
    cacheDirectory: path.resolve(__dirname, '.temp_cache')
  }
}

4: 模板联邦

跨项目间的chunk可以相互共享
1:UMD 模块


2: 微前端:多个项目共存于一个页面,有点类似iframe,共享的对象是项目级的,页面级的
子应用间的chunk以及对象可通过全局事件共享,但是公共包在项目安置以及打包编译很难放

  子应用独立打包,模块解耦了,但公共的依赖不易维护处理
  整体应用一起打包,能解决公共依赖;但庞大的多个项目又使打包变慢,后续也不好扩展

3:v5 的模块共享
这个方案是直接将一个应用的 bundle,应用于另一个应用,动态分发 runtime 子模块给其他应用。
模块联邦的使用方式如下:

module.exports = {
  // other webpack configs...
  plugins: [
    new ModuleFederationPlugin({
      // 1. name 当前应用名称,需要全局唯一
      name: "app_one_remote",
      // 2. remotes 可以将其他项目的 name 映射到当前项目中
      remotes: {
        app_two: "app_two_remote",
        app_three: "app_three_remote"
      },
      // 3. exposes 表示导出的模块,只有在此申明的模块才可以作为远程依赖被使用
      exposes: {
        AppContainer: "./src/App"
      },
      // 4. shared可以让远程加载的模块对应依赖改为使用本地项目的 React或ReactDOM。
      shared: ["react", "react-dom", "react-router-dom"]
    }),
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      chunks: ["main"]
    })
  ]
};

比如设置了remotes: { app_two: "app_two_remote" },在代码中就可以直接利用以下方式直接从对方应用调用模块

import { Search } from "app_two/Search";
app_two/Search来自于app_two 的配置:

// app_two的webpack 配置
export default {
  plugins: [
    new ModuleFederationPlugin({
      name: "app_two",
      library: { type: "var", name: "app_two" },
      filename: "remoteEntry.js",
      exposes: {
        Search: "./src/Search"
      },
      shared: ["react", "react-dom"]
    })
  ]
};

正是因为 Search在exposes被导出,我们因此可以使用 [name]/[exposes_name] 这个模块,这个模块对于被引用应用来说是一个本地模块。

4:构建优化 — 更好的Tree Shacking

v4 有些场景是不能将无用代码剔除的
1: 对于模块引入嵌套场景,如下b 是不会出现在生产代码里面的

// one.js
export const a = 1;
export const b = 2;

// two.js
import * as inner from "./inner";
export { inner }

// three.js
import * as module from "./module";
console.log(module.inner.a);

2:只有 test 方法使用了 someting 。最终可以实现标记更多没有使用的导出项

import { something } from "./something";

function usingSomething() {
return something;
}

export function test() {
return usingSomething();
}

3: Commondjs。现在Webpack不仅仅支持 ES module 的 tree Shaking,commonjs规范的模块开始支持了


更细致的讲解参考:
https://zhuanlan.zhihu.com/p/264826929
https://blog.csdn.net/P6P7qsW6ua47A2Sb/article/details/110015183

webpack dll: 将第三方库打包成dll.js ,这样修改应用代码只会构建应用的chunk,无关dll.js,加快速度,且浏览器缓存利好
https://www.cnblogs.com/skychx/p/webpack-dllplugin.html

hard-source-wepack-plugin:
https://segmentfault.com/a/1190000022453801

webpack 常用知识点
https://juejin.cn/post/6844904007362674701

你可能感兴趣的:(webpack5 新特性)