init 阶段:options
在上一节中,我们以 compiler 为主线探讨了 webpack 在 init 阶段的核心原理,在本节中我们将对 init 阶段 options 的处理进行更细化的探讨。
# 目录
# getNormalizedWebpackOptions
// lib/config/normalization.js
const getNormalizedWebpackOptions = configs => {
// ......
return normalizedConfigs;
};
1
2
3
4
5
2
3
4
5
这部分代码主要是校验和规整(normalize)options,代码很繁琐,甚至 option 都是按照字母顺序排序,与主流程关系不大,此处不再赘述。
不过可以借此机会,熟悉下 webpack 的 顶层options
有哪些?
# 顶层 option
webpack 配置有如下顶层 option。
option | 描述 |
---|---|
amd (opens new window) | 设置 require.amd 或 define.amd 的值。设置 amd 为 false 会禁用 webpack 的 AMD 支持。 |
bail (opens new window) | 在第一个错误出现时抛出失败结果,而不是容忍它。这将迫使 webpack 退出其打包过程。 |
cache (opens new window) | 缓存生成的 webpack 模块和 chunk,来改善 构建速度 。 |
context (opens new window) | 基础目录,绝对路径,用于从配置中解析入口点 (entry point) 和 加载器 (loader)。默认使用 Node.js 进程的当前工作目录。 |
dependencies (opens new window) | 一个 name 列表,定义它所依赖的所有兄弟(sibling)配置。需要首先编译依赖的配置。 |
devServer (opens new window) | 配置 webpack-dev-server |
devtool (opens new window) | 此选项控制是否生成,以及如何生成 source map。 |
entry (opens new window) | 开始应用程序打包过程的一个或多个起点。如果传入数组,则会处理所有条目。一个需要考虑的规则:每个 HTML 页面都有一个入口起点。单页应用 (SPA):一个入口起点,多页应用 (MPA):多个入口起点。 |
experiments (opens new window) | experiments 配置是在 webpack 5 中推出,目的是为了给用户赋能去开启并试用一些实验的特性。 |
externals (opens new window) | 防止将某些 import 的包 (package) 打包到 bundle 中,而是在运行时 (runtime) 再去从外部获取这些扩展依赖 (external dependencies)。 |
externalsPresets (opens new window) | 为特定的 target 启用 externals 的 preset。 |
externalsType (opens new window) | 指定 externals 的默认类型。当 external 被设置为 amd,umd,system 以及 jsonp 时,output.libraryTarget 的值也应相同。 |
ignoreWarnings (opens new window) | 告诉 webpack 忽略掉特定的警告。 |
infrastructureLogging (opens new window) | 用于基础设施水平的日志选项。 |
loader (opens new window) | 在 loader 上下文 中暴露自定义值。 |
mode (opens new window) | 提供 mode 配置选项,告知 webpack 使用相应模式的内置优化。 |
module (opens new window) | 这些选项决定了如何处理项目中的不同类型的模块。 |
name (opens new window) | 配置的名称。当加载不同的配置时会被使用。 |
node (opens new window) | 这些选项可以配置是否 polyfill 或 mock 某些 Node.js 全局变量。此功能由 webpack 内部的 NodeStuffPlugin 插件提供。 |
optimization (opens new window) | 从 webpack 4 开始,会根据你选择的 mode 来执行不同的优化, 不过所有的优化还是可以手动配置和重写。 |
output (opens new window) | output 位于对象最顶级键 (key),包括了一组选项,指示 webpack 如何去输出、以及在哪里输出你的「bundle、asset 和其他你所打包或使用 webpack 载入的任何内容」。 |
parallelism (opens new window) | 限制并行处理的模块数量。可以用于调优性能或获取更可靠的性能分析结果。 |
performance (opens new window) | 控制 webpack 如何通知「资源 (asset) 和入口起点超过指定文件限制」。 |
plugins (opens new window) | plugins 选项用于以各种方式自定义 webpack 构建过程。webpack 附带了各种内置插件,可以通过 webpack.[plugin-name] 访问这些插件。 |
profile (opens new window) | 捕获一个应用程序 "配置文件",包括统计和提示,然后可以使用 Analyze 分析工具进行详细分析。 |
recordsInputPath (opens new window) | 指定读取最后一条记录的文件的名称。这可以用来重命名一个记录文件。 |
recordsOutputPath (opens new window) | 指定记录要写入的位置。 |
resolve (opens new window) | 这些选项能设置模块如何被解析。webpack 提供合理的默认值,但是还是可能会修改一些解析的细节。 |
resolveLoader (opens new window) | 这组选项与上面的 resolve 对象的属性集合相同, 但仅用于解析 webpack 的 loader 包。 |
snapshot (opens new window) | snapshot 配置项决定文件系统是如何创建和无效快照。 |
stats (opens new window) | stats 选项让你更精确地控制 bundle 信息该怎么显示。 如果你不希望使用 quiet 或 noInfo 这样的不显示信息,而是又不想得到全部的信息,只是想要获取某部分 bundle 的信息,使用 stats 选项是比较好的折衷方式。 |
target (opens new window) | webpack 能够为多种环境或 target 构建编译。告知 webpack 为目标 (target) 指定一个环境。默认值为 "browserslist",如果没有找到 browserslist 的配置,则默认为 "web" |
watch (opens new window) | 启用 Watch 模式。这意味着在初始构建之后,webpack 将继续监听任何已解析文件的更改。 |
watchOptions (opens new window) | 一组用来定制 watch 模式的选项 |
参考:
# applyWebpackOptionsBaseDefaults 和 applyWebpackOptionsDefaults
这两个函数为 webpack 默认的 options 合并进应用配置的 options。
以 applyWebpackOptionsDefaults 为例:
context/target/devtool/watch/profile/parallelism/recordsInputPath/recordsOutputPath => cache => applySnapshotDefaults => applyModuleDefaults => applyOutputDefaults => applyExternalsPresetsDefaults => applyLoaderDefaults => externalsType => applyNodeDefaults => performance => applyPerformanceDefaults => applyOptimizationDefaults ......
1
下面开看下几个辅助函数:
// Sets a constant default value when undefined
const D = (obj, prop, value) => {
if (obj[prop] === undefined) {
obj[prop] = value;
}
};
// Sets a dynamic default value when undefined, by calling the factory function
const F = (obj, prop, factory) => {
if (obj[prop] === undefined) {
obj[prop] = factory();
}
};
//
const A = (obj, prop, factory) => {
const value = obj[prop];
if (value === undefined) {
obj[prop] = factory();
} else if (Array.isArray(value)) {
let newArray = undefined;
for (let i = 0; i < value.length; i++) {
const item = value[i];
if (item === "...") {
if (newArray === undefined) {
newArray = value.slice(0, i);
// 注意:newArray 是应用,赋值之后 newArray 仍然在变化
obj[prop] = newArray;
}
const items = factory();
if (items !== undefined) {
for (const item of items) {
newArray.push(item);
}
}
} else if (newArray !== undefined) {
newArray.push(item);
}
}
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# NodeEnvironmentPlugin
此插件初始化 Node 环境,包括日志组件 infrastructureLogger、文件 io 组件 inputFileSystem、文件 watch 组件 watchFileSystem。
class NodeEnvironmentPlugin {
apply(compiler) {
const { infrastructureLogging } = this.options;
// 初始化创建 infrastructureLogger
compiler.infrastructureLogger = createConsoleLogger(/** ...... */);
// 初始化文件系统相关,inputFileSystem 和 watchFileSystem
compiler.inputFileSystem = new CachedInputFileSystem(fs, 60000);
const inputFileSystem = compiler.inputFileSystem;
compiler.outputFileSystem = fs;
compiler.intermediateFileSystem = fs;
// this.watcher = new Watchpack(this.watcherOptions);
compiler.watchFileSystem = new NodeWatchFileSystem(
compiler.inputFileSystem
);
// 注册 Callback:Hook.beforeRun
compiler.hooks.beforeRun.tap("NodeEnvironmentPlugin", (compiler) => {
if (compiler.inputFileSystem === inputFileSystem) {
compiler.fsStartTime = Date.now();
inputFileSystem.purge();
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- inputFileSystem 和 watchFileSystem 分别是根据
enhanced-resolve
包和watchpack
实现的,链接见【参考】。
# WebpackOptionsApply
此组件(不具备 apply 方法,应该不视为 webpack 插件) 根据 options 注册内置插件。
代码位置:lib/WebpackOptionsApply.js
option | 插件 | 作用 | 备注 |
---|---|---|---|
externals | ExternalsPlugin | 从输出的 bundle 中排除依赖 | CompilerHook.compile => ExternalModuleFactoryPlugin => NormalModuleFactoryHook.factorize => handleExternals => handleExternal |
externalsPresets.node | NodeTargetPlugin | 将 node.js 的内置模块视为 external 模块(如 fs,path 或 vm),使用时通过 require () 加载。 | ExternalsPlugin("node-commonjs", builtins) |
externalsPresets.electronMain | ElectronTargetPlugin("main") | 将 main 上下文中的 electron 内置模块视为 external 模块(如 app,ipc-main 或 shell),使用时通过 require () 加载。 | ExternalsPlugin |
externalsPresets.electronPreload | ElectronTargetPlugin("preload") | 将预加载上下文的 electron 内置模块视为 external 模块(如 web-frame,ipc-renderer 或 shell),使用时通过 require () 加载。 | ExternalsPlugin |
externalsPresets.electronRenderer | ElectronTargetPlugin("renderer") | 将 renderer 上下文的 electron 内置模块视为 external 模块(如 web-frame、ipc-renderer 或 shell),使用时通过 require () 加载。 | ExternalsPlugin |
externalsPresets.electron | ElectronTargetPlugin | 将 main 和预加载上下文中常见的 electron 内置模块视为 external 模块(如 electron,ipc 或 shell),使用时通过 require () 加载。 | ExternalsPlugin |
externalsPresets.nwjs | ExternalsPlugin("node-commonjs", "nw.gui") | 将 NW.js 遗留的 nw.gui 模块视为 external 模块,使用时通过 require () 加载。 | ExternalsPlugin |
externalsPresets.webAsync | ExternalsPlugin("import") | 将 'http (s)😕/...' 以及'std:...' 的引用视为 external 模块,使用时通过 async import () 加载。(注意,此 external 类型为 async 模块,它对执行会产生各种副作用)。 | ExternalsPlugin |
externalsPresets.web | ExternalsPlugin("module") | 将 http (s)😕/... 以及 std:... 视为 external 模块,使用时通过 import 加载。(注意,这将改变执行顺序,因为 external 代码会在该块中的其他代码执行前被执行)。 | ExternalsPlugin |
ChunkPrefetchPreloadPlugin | CompilerHook.compilation => ...... | ||
output.chunkFormat | ArrayPushCallbackChunkFormatPlugin、CommonJsChunkFormatPlugin、ModuleChunkFormatPlugin | chunk 的格式(formats 默认包含 'array-push' (web/WebWorker)、'commonjs' (node.js)、'module' (ESM)) | |
output.enabledChunkLoadingTypes | EnableChunkLoadingPlugin | ||
output.enabledWasmLoadingTypes | EnableWasmLoadingPlugin | ||
output.enabledLibraryTypes | EnableLibraryPlugin | ||
output.pathinfo | ModuleInfoHeaderPlugin | ||
output.clean | CleanPlugin | ||
devtool | EvalSourceMapDevToolPlugin、SourceMapDevToolPlugin、EvalDevToolModulePlugin、EvalDevToolModulePlugin | ||
JavascriptModulesPlugin | |||
JsonModulesPlugin | |||
AssetModulesPlugin | |||
experiments.syncWebAssembly | WebAssemblyModulesPlugin | ||
experiments.asyncWebAssembly | AsyncWebAssemblyModulesPlugin | ||
experiments.css | CssModulesPlugin | ||
experiments.lazyCompilation | LazyCompilationPlugin | ||
experiments.buildHttp | HttpUriPlugin | ||
EntryOptionPlugin | |||
RuntimePlugin | |||
InferAsyncModulesPlugin | |||
DataUriPlugin | |||
FileUriPlugin | |||
CompatibilityPlugin (opens new window) | Currently useless. Ensures compatibility with other module loaders. | ||
HarmonyModulesPlugin | |||
options.amd | AMDPlugin、RequireJsStuffPlugin | ||
CommonJsPlugin | |||
LoaderPlugin | |||
APIPlugin | |||
ExportsInfoApiPlugin | |||
WebpackIsIncludedPlugin | |||
ConstPlugin | |||
UseStrictPlugin | |||
RequireIncludePlugin | |||
RequireEnsurePlugin | |||
RequireContextPlugin | |||
ImportPlugin | |||
ImportMetaContextPlugin | |||
SystemPlugin | |||
ImportMetaPlugin | |||
URLPlugin | |||
SystemPlugin | |||
WorkerPlugin | |||
DefaultStatsFactoryPlugin | |||
JavascriptMetaInfoPlugin | |||
options.mode | WarnNoModeSetPlugin | ||
EnsureChunkConditionsPlugin | |||
optimization.removeAvailableModules | RemoveParentModulesPlugin | ||
optimization.removeEmptyChunks | RemoveEmptyChunksPlugin | ||
optimization.mergeDuplicateChunks | MergeDuplicateChunksPlugin | ||
optimization.flagIncludedChunks | FlagIncludedChunksPlugin | ||
optimization.sideEffects | SideEffectsFlagPlugin | ||
optimization.providedExports | FlagDependencyExportsPlugin | ||
optimization.usedExports | FlagDependencyUsagePlugin | ||
optimization.innerGraph | InnerGraphPlugin | ||
optimization.mangleExports | MangleExportsPlugin | ||
optimization.concatenateModules | ModuleConcatenationPlugin | ||
optimization.splitChunks | SplitChunksPlugin | ||
optimization.emitOnErrors | NoEmitOnErrorsPlugin | ||
optimization.realContentHash | RealContentHashPlugin | ||
optimization.checkWasmTypes | WasmFinalizeExportsPlugin | ||
optimization.moduleIds | NaturalModuleIdsPlugin、NamedModuleIdsPlugin、WarnDeprecatedOptionPlugin、HashedModuleIdsPlugin、DeterministicModuleIdsPlugin、OccurrenceModuleIdsPlugin | ||
optimization.chunkIds | NaturalChunkIdsPlugin、NamedChunkIdsPlugin、DeterministicChunkIdsPlugin、OccurrenceChunkIdsPlugin | ||
optimization.nodeEnv | DefinePlugin (opens new window) | DefinePlugin 允许在 编译时 将你代码中的变量替换为其他值或表达式。这在需要根据开发模式与生产模式进行不同的操作时,非常有用。 | |
optimization.performance | SizeLimitsPlugin | ||
TemplatedPathPlugin | |||
RecordIdsPlugin | |||
WarnCaseSensitiveModulesPlugin | |||
AddManagedPathsPlugin | |||
cache | MemoryWithGcCachePlugin、MemoryCachePlugin、AddBuildDependenciesPlugin、IdleFileCachePlugin、PackFileCacheStrategy | ||
ResolverCachePlugin | |||
ignoreWarnings | IgnoreWarningsPlugin |
# 参考
编辑 (opens new window)
上次更新: 2022/09/06, 14:25:16