Skip to content

fix: narrow TemplatePathFn pathData type by context#20987

Merged
alexander-akait merged 7 commits into
mainfrom
claude/improve-path-types-P2Qvs
May 20, 2026
Merged

fix: narrow TemplatePathFn pathData type by context#20987
alexander-akait merged 7 commits into
mainfrom
claude/improve-path-types-P2Qvs

Conversation

@alexander-akait

Copy link
Copy Markdown
Member

Make TemplatePathFn generic over the PathData shape (defaults to the
existing fully-optional PathData) and add two narrowed variants in
Compilation.js:

  • PathDataChunk — chunk filename / chunk asset interpolation context,
    where chunk is always provided.
  • PathDataModule — module asset interpolation context, where module
    and chunkGraph are always provided.

Retype the public output option callbacks to use the appropriate
variant, so output.filename, output.chunkFilename,
output.cssFilename, output.cssChunkFilename,
output.htmlFilename, output.htmlChunkFilename, and the
optimization.splitChunks.cacheGroups[*].filename callback receive
PathDataChunk, while output.assetModuleFilename, the per-module
generator.filename / generator.outputPath (for asset/resource),
and module.parser.css.localIdentName receive PathDataModule.
output.publicPath keeps the loose PathData since it can be
interpolated in either context.

Also fix AssetResourceGeneratorOptions.filename and the combined
AssetGeneratorOptions.filename schemas to reference
AssetModuleFilename instead of FilenameTemplate — they were already
used as module-context filenames at runtime; the schema now matches.

Copilot AI review requested due to automatic review settings May 20, 2026 14:17
@changeset-bot

changeset-bot Bot commented May 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 59c953f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
webpack Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

This PR is packaged and the instant preview is available (3dd0b3b).

Install it locally:

  • npm
npm i -D webpack@https://pkg.pr.new/webpack@3dd0b3b
  • yarn
yarn add -D webpack@https://pkg.pr.new/webpack@3dd0b3b
  • pnpm
pnpm add -D webpack@https://pkg.pr.new/webpack@3dd0b3b

@codecov

codecov Bot commented May 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.94%. Comparing base (a39f2d3) to head (59c953f).

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #20987   +/-   ##
=======================================
  Coverage   90.94%   90.94%           
=======================================
  Files         573      573           
  Lines       58940    58941    +1     
  Branches    15888    15888           
=======================================
+ Hits        53601    53605    +4     
+ Misses       5339     5336    -3     
Flag Coverage Δ
integration 89.71% <100.00%> (+<0.01%) ⬆️
test262 45.36% <66.66%> (-0.01%) ⬇️
unit 36.58% <33.33%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refines webpack’s template-path callback typing by making TemplatePathFn generic over the pathData shape and then applying narrowed PathData variants in the public option callback types, so callback authors get stronger guarantees about what context fields are present.

Changes:

  • Introduces TemplatePathFn<T> plus PathDataChunk / PathDataModule and updates Compilation.getPath* signatures to carry the narrower pathData types through.
  • Retypes output/optimization/template callbacks to receive the appropriate context (PathDataChunk for chunk filenames, PathDataModule for module asset filenames).
  • Aligns asset generator option schemas and generated declarations to treat generator.filename as an asset-module (module-context) filename.

Reviewed changes

Copilot reviewed 16 out of 21 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
types.d.ts Updates generated public typings to use TemplatePathFn<T> and the narrowed PathDataChunk/PathDataModule in option callbacks and Compilation.getPath*.
schemas/WebpackOptions.json Updates schema references/tsType to use the narrowed callback typings and switches asset generator filename schemas to AssetModuleFilename.
schemas/plugins/asset/AssetResourceGeneratorOptions.check.js Regenerated validator output for updated schema.
schemas/plugins/asset/AssetGeneratorOptions.check.js Regenerated validator output for updated schema.
lib/TemplatedPathPlugin.js Adds generic JSDoc for TemplatePathFn<T> and updates interpolate signature typing.
lib/Template.js Updates RenderManifestEntryTemplated.filenameTemplate type to match the new generic callback shape.
lib/SourceMapDevToolPlugin.js Renames the local typedef used for append/sourceMappingURL comment typing (no behavior change).
lib/runtime/GetChunkFilenameRuntimeModule.js Retypes chunk filename template plumbing to use ChunkFilenameTemplate.
lib/runtime/AutoPublicPathRuntimeModule.js Small refactor to use a local chunk variable when computing the auto public path.
lib/optimize/SplitChunksPlugin.js Retypes cache group filename to the chunk-context template type.
lib/javascript/JavascriptModulesPlugin.js Retypes getChunkFilenameTemplate return type to ChunkFilenameTemplate.
lib/index.js Adds typedef imports for PathDataChunk / PathDataModule for surfaced typing.
lib/EvalSourceMapDevToolPlugin.js Removes an unused TemplatePath typedef.
lib/css/CssModulesPlugin.js Retypes chunk filename template return type for CSS chunks.
lib/Compilation.js Introduces PathDataChunk/PathDataModule typedefs and makes getPath* JSDoc generic over PathData.
lib/Chunk.js Defines ChunkFilenameTemplate JSDoc types and uses them for filenameTemplate fields.
lib/BannerPlugin.js Narrows banner interpolation pathData typing to chunk context.
lib/asset/AssetModulesPlugin.js Updates typedefs to treat asset module filename options as AssetModuleFilename.
declarations/WebpackOptions.d.ts Updates generated option typedefs to use TemplatePathFn<PathDataChunk> / TemplatePathFn<PathDataModule> in the appropriate places.
.changeset/narrow-path-data-types.md Adds a changeset documenting the typing narrowing as a patch change.
Files not reviewed (2)
  • schemas/plugins/asset/AssetGeneratorOptions.check.js: Language not supported
  • schemas/plugins/asset/AssetResourceGeneratorOptions.check.js: Language not supported
Comments suppressed due to low confidence (1)

schemas/WebpackOptions.json:217

  • AssetResourceGeneratorOptions.filename now references AssetModuleFilename, which (unlike FilenameTemplate) does not enforce minLength: 1 for strings. This makes filename: "" pass schema validation for asset/resource generator options. If empty filenames are not intended, consider tightening AssetModuleFilename (or wrapping it) to keep the non-empty constraint.
        "filename": {
          "$ref": "#/definitions/AssetModuleFilename"
        },

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

},
"filename": {
"$ref": "#/definitions/FilenameTemplate"
"$ref": "#/definitions/AssetModuleFilename"
@codspeed-hq

codspeed-hq Bot commented May 20, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

⚡ 5 improved benchmarks
❌ 3 regressed benchmarks
✅ 136 untouched benchmarks
⏩ 72 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Memory benchmark "future-defaults", scenario '{"name":"mode-production","mode":"production"}' 9 MB 7.3 MB +22.24%
Memory benchmark "side-effects-reexport", scenario '{"name":"mode-development","mode":"development"}' 4.9 MB 4.1 MB +21.78%
Memory benchmark "asset-modules-bytes", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 134.6 KB 323.3 KB -58.38%
Memory benchmark "three-long", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 682.3 KB 914.9 KB -25.42%
Memory benchmark "devtool-source-map", scenario '{"name":"mode-production","mode":"production"}' 5.5 MB 7.8 MB -29.75%
Memory benchmark "concatenate-modules", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 167.7 KB 133.7 KB +25.43%
Memory benchmark "asset-modules-resource", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 351.7 KB 255.6 KB +37.6%
Memory benchmark "many-chunks-commonjs", scenario '{"name":"mode-production","mode":"production"}' 9.3 MB 7.7 MB +20.8%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing claude/improve-path-types-P2Qvs (59c953f) with main (a39f2d3)

Open in CodSpeed

Footnotes

  1. 72 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Make `TemplatePathFn` generic over the `PathData` shape (defaults to the
existing fully-optional `PathData`) and add two narrowed variants in
`Compilation.js`:

- `PathDataChunk` — chunk filename / chunk asset interpolation context,
  where `chunk` is always provided.
- `PathDataModule` — module asset interpolation context, where `module`
  and `chunkGraph` are always provided.

Retype the public output option callbacks to use the appropriate
variant, so `output.filename`, `output.chunkFilename`,
`output.cssFilename`, `output.cssChunkFilename`,
`output.htmlFilename`, `output.htmlChunkFilename`, and the
`optimization.splitChunks.cacheGroups[*].filename` callback receive
`PathDataChunk`, while `output.assetModuleFilename`, the per-module
`generator.filename` / `generator.outputPath` (for `asset/resource`),
and `module.parser.css.localIdentName` receive `PathDataModule`.
`output.publicPath` keeps the loose `PathData` since it can be
interpolated in either context.

Also fix `AssetResourceGeneratorOptions.filename` and the combined
`AssetGeneratorOptions.filename` schemas to reference
`AssetModuleFilename` instead of `FilenameTemplate` — they were already
used as module-context filenames at runtime; the schema now matches.
The TemplatePathFn narrowing is a typing-only improvement to existing
public types, not a new feature; bump it as a patch.
- Switching AssetGeneratorOptions / AssetResourceGeneratorOptions
  filename schema refs from FilenameTemplate to AssetModuleFilename
  dropped the minLength: 1 string constraint. Restore it directly on
  AssetModuleFilename so empty strings stay invalid for both
  output.assetModuleFilename and the per-generator filename.
- Update the CLI snapshot whose entries for
  module.generator.asset.filename and
  module.generator.asset/resource.filename now pull the
  AssetModuleFilename description.
@alexander-akait alexander-akait force-pushed the claude/improve-path-types-P2Qvs branch from e2041d4 to 935329b Compare May 20, 2026 15:46
The minLength: 1 added to AssetModuleFilename in the previous commit
needed yarn fix:special to be re-run so the precompiled validators
match the schema source.
@alexander-akait alexander-akait changed the title feat: narrow TemplatePathFn pathData type by context fix: narrow TemplatePathFn pathData type by context May 20, 2026
A schema edit shipped to PR #20987 without re-running yarn fix:special;
the precompiled validators went stale and CI's lint job had to catch it.
Two changes so the next miss is caught at commit time instead.

- Promote the regenerate-after-schema/JSDoc/runtime-template rule in
  AGENTS.md to a [!REQUIRED] callout, enumerate the trigger paths, and
  recommend yarn fix (which already chains fix:code + fix:special + fmt)
  as the default pre-commit step.
- Add a lint-staged entry on schemas/**/*.json, tooling/generate-runtime-code.js,
  and tooling/generate-wasm-code.js that runs the read-only yarn lint:special
  (via tooling/lint-special-staged.js, which discards the file args lint-staged
  would otherwise append). Stale committed outputs now block the commit
  with the same error message CI reports.
Reverts the lint-staged wiring and tooling/lint-special-staged.js
helper added in 4d5b547; the [!REQUIRED] callout in AGENTS.md from
the same commit stays.
@github-actions

Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging claude/improve-path-types-P2Qvs into main will be
98.96%
Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
bin
   webpack.js98.77%100%100%98.77%91
examples
   build-common.js100%100%100%100%
   buildAll.js100%100%100%100%
   examples.js100%100%100%100%
   template-common.js98.21%100%100%98.21%72
examples/custom-javascript-parser
   test.filter.js100%100%100%100%
examples/custom-javascript-parser/internals
   acorn-parse.js100%100%100%100%
   meriyah-parse.js100%100%100%100%
   oxc-parse.js91.30%100%100%91.30%140, 142–143, 145, 147, 153–154, 161, 168, 90
examples/markdown
   webpack.config.mjs100%100%100%100%
examples/typescript
   test.filter.js100%100%100%100%
examples/typescript-non-erasable
   test.filter.js50%100%100%50%5
examples/virtual-modules
   test.filter.js100%100%100%100%
examples/wasm-bindgen-esm
   test.filter.js100%100%100%100%
examples/wasm-complex
   test.filter.js100%100%100%100%
examples/wasm-simple
   test.filter.js100%100%100%100%
examples/wasm-simple-source-phase
   test.filter.js100%100%100%100%
lib
   APIPlugin.js100%100%100%100%
   AsyncDependenciesBlock.js100%100%100%100%
   AutomaticPrefetchPlugin.js100%100%100%100%
   BannerPlugin.js100%100%100%100%
   Cache.js98.21%100%100%98.21%101
   CacheFacade.js100%100%100%100%
   Chunk.js99.72%100%100%99.72%39
   ChunkGraph.js100%100%100%100%
   ChunkGroup.js100%100%100%100%
   ChunkTemplate.js100%100%100%100%
   CleanPlugin.js99.15%100%100%99.15%206, 226
   CodeGenerationResults.js100%100%100%100%
   CompatibilityPlugin.js100%100%100%100%
   Compilation.js98.45%100%100%98.45%1572, 1868, 1875, 1883, 1905, 2801, 3226, 3888, 3917, 3970–3971, 3975, 3980, 3996–3997, 4011–4012, 4017–4018, 4495, 4521, 511, 516, 5229, 5261, 5278, 5294, 5310, 5325, 5350–5351, 5353, 5681, 5686, 5692, 5695, 5707, 5709, 5713, 5729, 5744, 5776, 5830, 5854, 5968, 730–731
   Compiler.js99.55%100%100%99.55%1116–1117, 1125
   ConcatenationScope.js98.59%100%100%98.59%189
   ConditionalInitFragment.js100%100%100%100%
   ConstPlugin.js100%100%100%100%
   ContextExclusionPlugin.js100%100%100%100%
   ContextModule.js100%100%100%100%
   ContextModuleFactory.js97.75%100%100%97.75%258, 393, 418, 443, 447, 458
   ContextReplacementPlugin.js100%100%100%100%
   DefinePlugin.js98.92%100%100%98.92%158–159, 175, 194, 268
   DependenciesBlock.js100%100%100%100%
   Dependency.js98.20%100%100%98.20%379, 425
   DependencyTemplate.js100%100%100%100%
   DependencyTemplates.js100%100%100%100%
   DotenvPlugin.js98.41%100%100%98.41%378, 391–392
   DynamicEntryPlugin.js100%100%100%100%
   EntryOptionPlugin.js100%100%100%100%
   EntryPlugin.js100%100%100%100%
   Entrypoint.js100%100%100%100%
   EnvironmentPlugin.js97.14%100%100%97.14%49
   ErrorHelpers.js100%100%100%100%
   EvalDevToolModulePlugin.js100%100%100%100%
   EvalSourceMapDevToolPlugin.js100%100%100%100%
   ExportsInfo.js100%100%100%100%
   ExportsInfoApiPlugin.js100%100%100%100%
   ExternalModule.js98.97%100%100%98.97%425–429, 577
   ExternalModuleFactoryPlugin.js100%100%100%100%
   ExternalsPlugin.js100%100%100%100%
   FileSystemInfo.js99.50%100%100%99.50%182, 2252–2253, 2256, 2267, 2278, 2289, 278, 3694, 3709, 3733
   FlagAllModulesAsUsedPlugin.js100%100%100%100%
   FlagDependencyExportsPlugin.js98.74%100%100%98.74%399, 401, 405
   FlagDependencyUsagePlugin.js100%100%100%100%
   FlagEntryExportAsUsedPlugin.js100%100%100%100%
   Generator.js100%100%100%100%
   HotModuleReplacementPlugin.js100%100%100%100%
   HotUpdateChunk.js100%100%100%100%
   IgnorePlugin.js100%100%100%100%
   IgnoreWarningsPlugin.js100%100%100%100%
   InitFragment.js100%100%100%100%
   JavascriptMetaInfoPlugin.js100%100%100%100%
   LibraryTemplatePlugin.js100%100%100%100%
   LoaderOptionsPlugin.js100%100%100%100%
   LoaderTargetPlugin.js100%100%100%100%
   MainTemplate.js100%100%100%100%
   ManifestPlugin.js100%100%100%100%
   Module.js98.50%100%100%98.50%1305, 1310, 1371, 1385, 1447, 1456
   ModuleFactory.js100%100%100%100%
   ModuleFilenameHelpers.js98.85%100%100%98.85%106, 108
   ModuleGraph.js99.73%100%100%99.73%1004
   ModuleGraphConnection.js100%100%100%100%
   ModuleInfoHeaderPlugin.js100%100%100%100%
   ModuleNotFoundError.js100%100%100%100%
   ModuleProfile.js100%100%100%100%
   ModuleSourceTypeConstants.js100%100%100%100%
   ModuleTemplate.js100%100%100%100%
   ModuleTypeConstants.js100%100%100%100%
   MultiCompiler.js99.69%100%100%99.69%645
   MultiStats.js100%100%100%100%
   MultiWatching.js100%100%100%100%
   NoEmitOnErrorsPlugin.js100%100%100%100%
   NodeStuffPlugin.js100%100%100%100%
   NormalModule.js97.78%100%100%97.78%1020, 1036, 1123, 1774, 1779–1789, 708, 711, 728, 745, 986
   NormalModuleFactory.js99.47%100%100%99.47%1075, 1384, 474, 486
   NormalModuleReplacementPlugin.js100%100%100%100%
   NullFactory.js100%100%100%100%
   OptimizationStages.js100%100%100%100%
   OptionsApply.js100%100%100%100%
   Parser.js100%100%100%100%
   PlatformPlugin.js100%100%100%100%
   PrefetchPlugin.js100%100%100%100%
   ProgressPlugin.js98.85%100%100%98.85%519–520, 525, 527, 591
   ProvidePlugin.js100%100%100%100%
   RawModule.js100%100%100%100%
   RecordIdsPlugin.js100%100%100%100%
   RequestShortener.js100%100%100%100%
   ResolverFactory.js100%100%100%100%
   RuntimeGlobals.js100%100%100%100%
   RuntimeModule.js100%100%100%100%
   RuntimePlugin.js100%100%100%100%
   RuntimeTemplate.js100%100%100%100%
   SelfModuleFactory.js100%100%100%100%
   SingleEntryPlugin.js100%100%100%100%
   SourceMapDevToolModuleOptionsPlugin.js100%100%100%100%
   SourceMapDevToolPlugin.js99.16%100%100%99.16%267–268, 610
   Stats.js100%100%100%100%
   Template.js100%100%100%100%
   TemplatedPathPlugin.js98.86%100%100%98.86%136–137
   UseStrictPlugin.js100%100%100%100%
   WarnCaseSensitiveModulesPlugin.js100%100%100%100%
   WarnDeprecatedOptionPlugin.js100%100%100%100%
   WarnNoModeSetPlugin.js100%100%100%100%
   WatchIgnorePlugin.js100%100%100%100%
   Watching.js100%100%100%100%
   WebpackError.js100%100%100%100%
   WebpackIsIncludedPlugin.js100%100%100%100%
   WebpackOptionsApply.js100%100%100%100%
   WebpackOptionsDefaulter.js100%100%100%100%
   buildChunkGraph.js99.87%100%100%99.87%325
   cli.js98.46%100%100%98.46%10, 119, 471, 503, 545, 815
   index.js99.72%100%100%99.72%165
   validateSchema.js94.67%100%100%94.67%100, 87, 89, 98
   webpack.js96.33%100%100%96.33%10, 198, 220, 222
lib/asset
   AssetBytesGenerator.js100%100%100%100%
   AssetBytesParser.js100%100%100%100%
   AssetGenerator.js100%100%100%100%
   AssetModulesPlugin.js97.33%100%100%97.33%287, 311, 314, 366, 37, 42
   AssetParser.js100%100%100%100%
   AssetSourceGenerator.js100%100%100%100%
   AssetSourceParser.js100%100%100%100%
   RawDataUrlModule.js100%100%100%100%
lib/async-modules
   AsyncModuleHelpers.js100%100%100%100%
   AwaitDependenciesInitFragment.js100%100%100%100%
   InferAsyncModulesPlugin.js100%100%100%100%
lib/cache
   AddBuildDependenciesPlugin.js100%100%100%100%
   AddManagedPathsPlugin.js100%100%100%100%
   IdleFileCachePlugin.js97.92%100%100%97.92%71, 83, 91
   MemoryCachePlugin.js95.83%100%100%95.83%33
   MemoryWithGcCachePlugin.js93.15%100%100%93.15%106, 113–114, 122, 89
   PackFileCacheStrategy.js96.40%100%100%96.40%1250, 1350, 1354, 1416, 628, 647, 657–659, 661, 677–678, 683, 686, 688, 693, 698, 722, 728, 762, 768, 774, 779, 790, 799, 804–805, 807, 824, 830–831, 833
   ResolverCachePlugin.js100%100%100%100%
   getLazyHashedEtag.js100%100%100%100%
   mergeEtags.js100%100%100%100%
lib/config
   browserslistTargetHandler.js100%100%100%100%
   defaults.js99.29%100%100%99.29%1411–1413, 1421, 271, 274, 279, 283
   normalization.js99%100%100%99%191–192, 258, 273
   target.js100%100%100%100%
lib/container
   ContainerEntryDependency.js100%100%100%100%
   ContainerEntryModule.js100%100%100%100%
   ContainerEntryModuleFactory.js100%100%100%100%
   ContainerExposedDependency.js100%100%100%100%
   ContainerPlugin.js100%100%100%100%
   ContainerReferencePlugin.js100%100%100%100%
   FallbackDependency.js100%100%100%100%
   FallbackItemDependency.js100%100%100%100%
   FallbackModule.js100%100%100%100%
   FallbackModuleFactory.js100%100%100%100%
   

@alexander-akait alexander-akait merged commit 3dd0b3b into main May 20, 2026
60 of 61 checks passed
@alexander-akait alexander-akait deleted the claude/improve-path-types-P2Qvs branch May 20, 2026 18:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants