# Data flow — webpack/webpack

> Canonical page: https://codevetter.com/unpack/webpack/data-flow

# Data flow — webpack/webpack

Scanned commit 87a62dec2304cd2c163c41feeeb43fbe3e5c21dd (2026-09-22). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Input boundaries are the config object (validated against JSON Schema), the input filesystem behind `InputFileSystem`, and optionally the network (`HttpUriPlugin`) or a data/virtual URL scheme. A request becomes a module through `NormalModuleFactory.create` (resolve → rules match → factory hooks), is read and transformed by the loader chain in `LoaderRunner`, then parsed into `Dependency` objects that populate the `ModuleGraph`. At seal time the `ModuleGraph` is frozen and `buildChunkGraph` fills a `ChunkGraph`; code generation renders each module through its `Generator` and `DependencyTemplate`s into `Source` objects, which are hashed, assembled into assets, passed through the `processAssets` stage pipeline, and finally written by `Compiler.emitAssets` through `OutputFileSystem`. Everything durable — module graph, code generation results, resolver results — round-trips through `lib/serialization/` into the filesystem cache pack.
- Input normalization is two distinct layers: `normalization.js` canonicalizes the user's config shape (shorthand → full form, 828 lines) and `defaults.js` fills mode/target-dependent values (2,889 lines); `applyWebpackOptionsBaseDefaults` runs before plugins and `applyWebpackOptionsDefaults` after. — [lib/config/normalization.js](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/config/normalization.js) [lib/config/defaults.js](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/config/defaults.js) [lib/webpack.js#L143-175](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/webpack.js#L143-L175)
- `NormalModuleFactory.create` builds a single mutable `ResolveData` object carrying `contextInfo`, `request`, `phase`, import `attributes`, `createData`, and three `LazySet`s of file/missing/context dependencies, then drives it through `beforeResolve` → `factorize` → `resolve` → `afterResolve` → `createModule` → `module`. — [lib/module/NormalModuleFactory.js#L1269-1345](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/module/NormalModuleFactory.js#L1269-L1345) [lib/module/NormalModuleFactory.js#L628-676](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/module/NormalModuleFactory.js#L628-L676)
- Loader selection is a compiled rule set: `NormalModuleFactory`'s constructor compiles `options.defaultRules` and `options.rules` together via `ruleSetCompiler.compile`, so `module.rules` matching is a precompiled matcher rather than a per-request scan. — [lib/module/NormalModuleFactory.js#L679-690](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/module/NormalModuleFactory.js#L679-L690) [lib/rules/RuleSetCompiler.js#L141-200](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/rules/RuleSetCompiler.js#L141-L200)
- Source text enters through `NormalModule._doBuild`, which calls the vendored `runLoaders` with a `processResource` callback; the loader chain is executed as a pitching pass then a normal pass (`iteratePitchingLoaders` → `processResource` → unwind), and each loader module is loaded by `loadLoader`. — [lib/module/NormalModule.js#L1339-1470](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/module/NormalModule.js#L1339-L1470) [lib/loaders/LoaderRunner.js#L503-580](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/loaders/LoaderRunner.js#L503-L580) [lib/loaders/LoaderRunner.js#L812-870](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/loaders/LoaderRunner.js#L812-L870)
- The loader chain can bypass parsing entirely: a loader may return `webpackAST` in its `additionalData`, which `LoaderRunner` types as `AdditionalDataKnown.webpackAST` — "the AST webpack should parse instead of the source". — [lib/loaders/LoaderRunner.js#L49-56](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/loaders/LoaderRunner.js#L49-L56)
- Cacheability is data that flows back out of the loader chain: `RunLoaderResult` carries `cacheable`, `notCacheableReasons`, and the `fileDependencies`/`contextDependencies`/`missingDependencies` lists that `FileSystemInfo` later snapshots to decide staleness. — [lib/loaders/LoaderRunner.js#L36-46](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/loaders/LoaderRunner.js#L36-L46) [lib/loaders/LoaderRunner.js#L710-715](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/loaders/LoaderRunner.js#L710-L715) [lib/fs/FileSystemInfo.js](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/fs/FileSystemInfo.js)
- State ownership is explicit: the `Compilation` owns `modules`, `entries`, `chunks`, the `ModuleGraph` and `ChunkGraph`, and five work queues (`factorizeQueue`, `buildQueue`, `rebuildQueue`, `processDependenciesQueue`, `addModuleQueue`) which `seal`'s `finalCallback` clears on completion. — [lib/Compilation.js#L3612-3632](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/Compilation.js#L3612-L3632) [lib/graph/ModuleGraph.js](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/graph/ModuleGraph.js) [lib/graph/ChunkGraph.js](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/graph/ChunkGraph.js)
- `seal` freezes the module graph with `this.moduleGraph.freeze("seal")` before building chunks, then materializes one `Chunk` + `Entrypoint` per entry and seeds `chunkGraphInit` with each entry's resolved modules, validating `dependOn`/`runtime` conflicts and circular `dependOn` into `compilation.errors`. — [lib/Compilation.js#L3648-3700](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/Compilation.js#L3648-L3700) [lib/Compilation.js#L3717-3790](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/Compilation.js#L3717-L3790)
- After chunking, the ordered tail of `seal` is `processRuntimeRequirements` → `_attachPendingRuntimeModules` → `createHash` (which returns the code-generation jobs) → `_runCodeGenerationJobs` → `createModuleAssets` → `createChunkAssets` → `processAssets` → freeze `this.assets` → `summarizeDependencies` → `afterSeal`. — [lib/Compilation.js#L3900-3999](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/Compilation.js#L3900-L3999) [lib/Compilation.js#L5174-5200](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/Compilation.js#L5174-L5200) [lib/Compilation.js#L5883-5900](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/Compilation.js#L5883-L5900)
- `this.assets` is frozen at the end of `processAssets` — literally `Object.freeze` when `backCompat` is off, and a `soonFrozenObjectDeprecation` proxy carrying `DEP_WEBPACK_COMPILATION_ASSETS` when it is on — so post-seal asset mutation is a hard boundary. — [lib/Compilation.js#L3945-3965](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/Compilation.js#L3945-L3965)
- The output boundary is `Compiler.emitAssets`, which writes at most 15 assets concurrently, recomputes `immutable` when a query/hash suffix is stripped, special-cases Windows drive-absolute target paths via `WINDOWS_ABS_PATH_REGEXP`, and refuses to write two assets whose paths differ only by casing or query string. — [lib/Compiler.js#L786-900](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/Compiler.js#L786-L900)
- Emitted-asset writes are deduplicated through two caches on the compiler — `_assetEmittingWrittenFiles` (path → generation) and `_assetEmittingSourceCache` (Source → `{ sizeOnlySource, writtenTo }`) — so an unchanged `Source` in a watch rebuild is compared rather than rewritten. — [lib/Compiler.js#L848-900](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/Compiler.js#L848-L900)
- Records are a separate persisted side-channel from the cache: `Compiler.readRecords` runs before `compile` and `emitRecords` after `emitAssets`, and `RecordIdsPlugin` uses them to keep module/chunk ids stable across builds via `recordsPath`. — [lib/Compiler.js#L1302-1400](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/Compiler.js#L1302-L1400) [lib/Compiler.js#L688-700](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/Compiler.js#L688-L700) [lib/ids/RecordIdsPlugin.js](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/ids/RecordIdsPlugin.js)
- Build dependencies close the loop into the cache: after `done`, `run`'s final step is `this.cache.storeBuildDependencies(compilation.buildDependencies, compilation.optionalBuildDependencies, …)`, which `PackFileCacheStrategy` snapshots into the `PackContainer` alongside a version string. — [lib/Compiler.js#L672-686](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/Compiler.js#L672-L686) [lib/cache/PackFileCacheStrategy.js#L57-110](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/cache/PackFileCacheStrategy.js#L57-L110) [lib/cache/IdleFileCachePlugin.js#L99-110](https://github.com/webpack/webpack/blob/87a62dec2304cd2c163c41feeeb43fbe3e5c21dd/lib/cache/IdleFileCachePlugin.js#L99-L110)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
