ModuleConcatenationPlugin

2023-06-03 14:51 更新

在过去,webpack在捆绑时的一个权衡是,你的捆绑包中的每个模块都将被包装在单独的函数闭包中。这些包装器函数降低了JavaScript在浏览器中的执行速度。相比之下,像Closure Compiler和RollupJS这样的工具可以将所有模块的作用域“提升”或连接到一个闭包中,并允许你的代码在浏览器中有更快的执行时间。

这个插件将在webpack中启用相同的连接行为。默认情况下,该插件已在生产模式下启用,否则禁用。如果需要覆盖生产模式优化,请设置 ​optimization.concatenateModules​ 选择为 ​false​。要在其他模式下启用连接行为,您可以手动添加 ​ModuleConcatenationPlugin​ 或使用优化。optimization.concatenateModules 选择:

new webpack.optimize.ModuleConcatenationPlugin();

这种连接行为称为“作用域提升”。作用域提升是ECMAScript模块语法实现的一个特性。因此,webpack可能会根据您使用的模块类型和其他条件退回到正常的捆绑。

Optimization Bailouts

正如文章所解释的,webpack试图实现部分作用域提升。它会将模块合并到单个作用域中,但不能在所有情况下都这样做。如果webpack不能合并一个模块,两个替代选项是Prevent和Root。Prevent意味着模块必须在它自己的作用域中。Root表示将创建一个新的模块组。以下条件决定了结果:

Condition Outcome
Non ES6 Module Prevent
Imported By Non Import Root
Imported From Other Chunk Root
Imported By Multiple Other Module Groups Root
Imported With import() Root
Affected By ProvidePlugin Or Using module Prevent
HMR Accepted Root
Using eval() Prevent
In Multiple Chunks Prevent
export * from "cjs-module" Prevent

Module Grouping Algorithm

下面的伪JavaScript解释了该算法:

modules.forEach((module) => {
  const group = new ModuleGroup({
    root: module,
  });
  module.dependencies.forEach((dependency) => {
    tryToAdd(group, dependency);
  });
  if (group.modules.length > 1) {
    orderedModules = topologicalSort(group.modules);
    concatenatedModule = new ConcatenatedModule(orderedModules);
    chunk.add(concatenatedModule);
    orderedModules.forEach((groupModule) => {
      chunk.remove(groupModule);
    });
  }
});

function tryToAdd(group, module) {
  if (group.has(module)) {
    return true;
  }
  if (!hasPreconditions(module)) {
    return false;
  }
  const nextGroup = group;
  const result = module.dependents.reduce((check, dependent) => {
    return check && tryToAdd(nextGroup, dependent);
  }, true);
  if (!result) {
    return false;
  }
  module.dependencies.forEach((dependency) => {
    tryToAdd(group, dependency);
  });
  group.merge(nextGroup);
  return true;
}

Debugging Optimization Bailouts

当使用webpack CLI时,​——stats-optimization-bailout​ 标志将显示救助原因。当使用webpack配置时,在 ​stats​ 对象中添加以下内容:

module.exports = {
  //...
  stats: {
    // Display bailout reasons
    optimizationBailout: true,
  },
};


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号