按顺序执行 Webpack 打包程序

Posted

技术标签:

【中文标题】按顺序执行 Webpack 打包程序【英文标题】:Executing Webpack bundlers in sequence 【发布时间】:2018-12-19 06:02:29 【问题描述】:

我将首先描述上下文,我希望理想的情况是什么以及到目前为止我已经尝试过什么。

上下文

我正在尝试使用 Webpack 构建一个直接的 React 应用程序。我将此应用程序称为核心。最重要的是,有一个可选的 branding 可以由 Webpack 捆绑,它查看给定的品牌目录,获取资产并使用其自己的加载器和输出策略转换自定义 SASS。然后,它会用品牌特定的资产(想想网站图标、徽标、背景)覆盖核心使用的默认资产。

结构如下:

我有几个 webpack 配置文件,

webpack.dev.js --配置指定 env 和 dev-server 配置并将其与核心和品牌合并 webpack.prod.js --指定环境和缩小插件的小配置,并将其与核心和品牌合并 webpack.branding.js --声明品牌特定捆绑规则并与通用合并 webpack.core.js --声明核心特定的捆绑规则并与通用合并 webpack.generic.js --提供品牌和核心使用的通用配置

目前情况下这些文件的来源可以在this gist找到。

理想情况

核心应该能够完全独立运行,使用默认资产。当一个 dev/prod 构建过程开始时,它将同时运行核心和品牌,除非明确告知要独占运行。

品牌也应该能够建立在它自己的基础上,从而形成一个只包含品牌资产的小包。该过程应该足够灵活,以便品牌化 dist 应该能够替换 dist 核心文件夹中的任何文件,而无需核心重新编译和重建引用。目前,这些资产仅限于 CSS 文件 (branding.css) 和一些图像资产。

我的尝试

我曾尝试使用内置的 Webpack multicompiler 同时运行核心和品牌 (module.exports = [core, branding]),但我无法指定 Webpack 运行核心和品牌流程的顺序因为它并行运行它们。由于品牌塑造过程要小得多,它总是会先完成,从而导致品牌资产被默认覆盖。

我曾尝试使用webpack-merge 合并核心和品牌配置文件,但这不起作用,因为我为两者指定了不同的输出规则。核心在其输出命名约定中使用内容哈希,而品牌没有。这在尝试合并时效果不佳。使用merge.multiple() 时,我将获得每个文件中的两个,一个带有哈希值,一个没有哈希值,或者在使用merge.smart() 时,我将只获得由单个配置指定的每个文件之一,带有哈希值或不带有哈希值(取决于合并顺序)。

我尝试使用 && 命令 ("build": "webpack --config webpack.core.js && webpack --config webpack.branding.js --branding <brand>") 从我的 npm 脚本中按顺序运行核心和品牌。这不能与 webpack-dev-server 协同工作。

提前感谢您提供任何帮助和/或建议。如有必要,我会用更多信息更新我的问题。

【问题讨论】:

您最终找到解决方案了吗?我有完全相同的要求(按顺序运行两个配置,支持 webpack-dev-server)。 最糟糕的是文档说 MultiCompiler 应该以 sequence 运行,而不是并行运行!似乎有些不对劲...webpack.js.org/api/node/#multicompiler 【参考方案1】:

我知道这不是对您问题的直接回答,但我将其留在这里是为了帮助其他人解决表面上看起来与您的问题完全相同的问题:

认为我遇到了完全相同的问题,因为我的“应用程序”配置(它使用DllPlugin 来引用它的“lib”包)构建失败,因为它的“lib”依赖项的 DLL 清单不是t 尚未生成。这让我想到,也许配置是并行运行的,而不是像 webpack 文档所说的那样按顺序运行(这感觉很奇怪,但有时确实会发生错误)。

但是(我认为我的两个配置在不同的文件中这一事实加剧了这种情况),我没有立即注意到一个重要的细节:实际的配置本身是立即加载的,不是是时候建造了。因此,我的DllReferencePlugin 配置尝试在运行任何配置之前立即加载 DLL 清单:

new webpack.DllReferencePlugin(
  manifest: require(path.join(tempDir, "/lib.dll-manifest.json"))
),

幸运的是,manifest 选项允许传递路径而不是预加载清单对象。使用绝对路径允许DllReferencePlugin 仅在配置运行时加载清单:

new webpack.DllReferencePlugin(
  manifest: path.join(tempDir, "/lib.dll-manifest.json")
),

回想起来,这是一件很小的“显而易见”的事情。但是在大型 webpack 配置中很容易错过。

所以如果你有类似的问题,可能是你的依赖 webpack 配置太早了,在依赖有机会自己生成文件之前。使用 node 的 --inspect-brk 和调试器(VS Code)进入构建脚本和 webpack 配置帮助我找到了根本原因。


顺便说一句,我还看到提到了 namedependencies 配置选项,但在文档中没有找到太多(如果有的话)信息:

const configA = 
  name: "lib",
  entry: ...
  ...


const configB = 
  name: "app",
  dependencies: ["lib"]
  entry: ...
  ...

This 和 this 证明该功能存在,即使文档中没有提及。 虽然我没有测试过,但您也许可以通过这种方式定义您想要的构建顺序。 最后,这似乎也是难题的重要组成部分。如果没有 namedependencies 属性,webpack 似乎假设它可以并行运行配置,至少从 webpack 4.25.1 开始。

【讨论】:

以上是关于按顺序执行 Webpack 打包程序的主要内容,如果未能解决你的问题,请参考以下文章

Webpack Loader种类以及执行顺序

webpack打包原理

webpack 样式模块打包深入学习

webpack中loader为啥是从后往前加载的

Webpack自定义loader的执行顺序实战分析

Webpack