webpack/webpack
Extension is the architecture: everything user-visible is a plugin that taps `tapable` hooks, and webpack's own features are implemented the same way user plugins are. The four main seams are (1) the hook objects on `Compiler`, `Compilation` and `NormalModuleFactory`, including `HookMap`s keyed by module type; (2) the `Dependency` + `DependencyTemplate` + `makeSerializable` triple for new dependency kinds; (3) `RuntimeGlobals` + `RuntimeModule` + `runtimeRequirementInTree` for new runtime code; and (4) the plugin-based `RuleSetCompiler` for new `module.rules` vocabulary. Generators of tables and types are themselves extension points — a new CSS math function or HTML attribute is a descriptor added to a `tooling/generate-*-data.js` SUPPLEMENT, not code added to a printer.
- `NormalModuleFactory.hooks` is the richest factory seam: `resolve`, `factorize`, `beforeResolve`, `afterResolve`, `createModule`, `module`, plus five `HookMap`s keyed by scheme or module type (`resolveForScheme`, `resolveInScheme`, `prepareModuleType`, `createParser`/`parser`, `createGenerator`/`generator`, `createModuleClass`), several annotated with `@since` versions.
- New URL schemes plug in through `resolveForScheme`/`resolveInScheme` — the pattern used by `DataUriPlugin`, `FileUriPlugin`, `HttpUriPlugin` and `VirtualUrlPlugin` in `lib/schemes/`.
- A new module language is a parser/generator pair registered on the type-keyed HookMaps and cached per options object in `parserCache`/`generatorCache`; `lib/module/Parser.js` and `lib/module/Generator.js` are the base classes, both re-exported publicly as `webpack.Parser` / `webpack.Generator`.
- A new dependency type is the documented triple: a `Dependency` subclass in `lib/dependencies/`, a `DependencyTemplate` registered into `compilation.dependencyTemplates`, and a `makeSerializable(Class, "webpack/lib/…")` call — the pattern appears in 144 files.
- New runtime code plugs in via `lib/runtime/RuntimeGlobals.js` (97 exported symbols), a `RuntimeModule` subclass, and a tap on `runtimeRequirementInTree`/`additionalTreeRuntimeRequirements`; `RuntimePlugin` is what injects modules for the requirements a build collects.
- `module.rules` vocabulary is itself pluggable: `RuleSetCompiler` is constructed from rule plugins (`BasicMatcherRulePlugin`, `ObjectMatcherRulePlugin`, `GlobMatcherRulePlugin`, `BasicEffectRulePlugin`, `UseEffectRulePlugin`), so a new condition or effect keyword is a new plugin rather than a branch in the matcher.
- Target support is a table-driven registry: adding a target means adding a `[name, description, regExp, handler]` tuple to `TARGETS` in `lib/config/target.js`, and `mergeTargetProperties` plus `UNSUPPORTED_WHEN_ABSENT` decide how multi-target arrays like `["web", "node"]` resolve each capability.
- Chunk-loading, wasm-loading and library formats are enabled through dedicated dispatch plugins — `EnableChunkLoadingPlugin`, `EnableWasmLoadingPlugin`, `EnableLibraryPlugin` — which `WebpackOptionsApply` calls per configured type, so a new format registers itself with one of these rather than editing the option branch.
- Stats output is extensible through the factory/preset/printer split: `DefaultStatsFactoryPlugin` builds the object graph, `DefaultStatsPresetPlugin` defines named presets, and `DefaultStatsPrinterPlugin` renders it — each a separate tap point.
- Module Federation exposes its own hook surface in `lib/container/moduleFederationHooks.js` and `lib/hmr/parserHooks.js` does the same for HMR, so third-party federation/HMR tooling taps a published hook object rather than reaching into the plugin.
- Caches are pluggable at the `Cache`/`CacheFacade` layer: `MemoryCachePlugin`, `MemoryWithGcCachePlugin`, `IdleFileCachePlugin` and `ResolverCachePlugin` all tap `compiler.cache.hooks.{get,store,storeBuildDependencies}`, so an alternative backing store is a plugin.
- Per-construct minifier behaviour is table-driven by design: the generators own the descriptors (`MATH_FUNCTION_FOLD` in `tooling/generate-css-data.js`, `SUPPLEMENT`/`PARSER_TABLES` in `generate-html-data.js`) and the printers implement only the shared engine keyed by them, so adding a foldable function is adding a generator entry.
- Custom filesystems plug in behind the `InputFileSystem`/`OutputFileSystem` interfaces declared in `lib/fs/fs.js`; `NodeEnvironmentPlugin` supplies the Node-backed defaults and a target may supply its own watcher (`NodeWatchFileSystem`).
- Schema-driven options are their own extension point: adding a property to `schemas/WebpackOptions.json` regenerates the CLI flag list (`webpack.cli.getArguments`), the precompiled validator, the declaration and the `types.d.ts` member in one `yarn fix:special` run.