Skip to content

Claude/solve issue 20976 g8i yo#20978

Merged
alexander-akait merged 6 commits into
mainfrom
claude/solve-issue-20976-g8iYO
May 19, 2026
Merged

Claude/solve issue 20976 g8i yo#20978
alexander-akait merged 6 commits into
mainfrom
claude/solve-issue-20976-g8iYO

Conversation

@alexander-akait

Copy link
Copy Markdown
Member

Summary

feat - ability to control order

What kind of change does this PR introduce?

feat

Did you add tests for your changes?

Yes

Does this PR introduce a breaking change?

No

If relevant, what needs to be documented once your changes are merged or what have you already documented?

New hook

Use of AI

Yes

…CSS module ordering

Add optimization.cssModulesOrder ("import" | "name", default "import"). With
"name", CssModulesPlugin emits a chunk's CSS modules in deterministic full-name
order and skips the topological merge across chunk groups, so the "Conflicting
order between css ..." warning is no longer produced. Useful when migrating
from mini-css-extract-plugin to the builtin CSS support and when CSS modules
rarely share classnames across files. Closes #20976.
…dulesPlugin orderModules hook

Drop the optimization.cssModulesOrder option introduced in the previous commit
in favor of a more general SyncBailHook on CssModulesPlugin's compilation
hooks: orderModules(chunk, modules, compilation). Modules arrive pre-sorted by
full module name. A tap returning Module[] overrides the default import-order
topological sort (and so suppresses the "Conflicting order" warning); returning
undefined keeps the default. This avoids committing webpack core to a specific
ordering algorithm while still letting users (and dedicated plugins) solve the
discussion #20976 use case.
Add three configCases that exercise the new CssModulesPlugin orderModules hook:
- css-modules-order-priority: pin a specific file (e.css) to the front and
  keep the rest in name order — practical "reset.css first" pattern.
- css-modules-order-fallback: tap returns undefined and webpack falls back
  to its default import-order topological sort, including the Conflicting
  order warning (asserted via warnings.js).
- css-modules-order-multi-tap: two taps where the first wins and the second
  throws if reached, locking in SyncBailHook short-circuit semantics.
Copilot AI review requested due to automatic review settings May 18, 2026 17:23
@changeset-bot

changeset-bot Bot commented May 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f528d02

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

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

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 18, 2026

Copy link
Copy Markdown
Contributor

This PR is packaged and the instant preview is available (561ee9b).

Install it locally:

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

…nfig configCase

Replace the four separate test directories with a single
test/configCases/css/css-modules-order-hook/ that exports a webpack
configuration array, exercising all four scenarios in one place:

- name: tap returns modules as-is (modules arrive pre-sorted by full name)
- priority: tap pins e.css to the front while keeping the rest in name order
- fallback: tap returns undefined and webpack applies its default
  topological sort (the "Conflicting order" warning is still emitted)
- multi-tap: two taps where the first wins and the second throws if reached,
  asserting SyncBailHook short-circuit semantics

The shared CSS fixtures are deduplicated to a single copy, scenario
assertions live in per-entry files via a tiny helper, and the expected
fallback warning is captured in warnings.js (MultiStats aggregates child
warnings into the top-level array).
@codecov

codecov Bot commented May 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.91%. Comparing base (a5966b8) to head (f528d02).
⚠️ Report is 6 commits behind head on main.

❌ Your changes status has failed because you have indirect coverage changes. Learn more about Unexpected Coverage Changes and reasons for indirect coverage changes.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #20978      +/-   ##
==========================================
- Coverage   90.92%   90.91%   -0.02%     
==========================================
  Files         571      573       +2     
  Lines       58301    58616     +315     
  Branches    15659    15764     +105     
==========================================
+ Hits        53009    53289     +280     
- Misses       5292     5327      +35     
Flag Coverage Δ
integration 89.60% <100.00%> (-0.05%) ⬇️
test262 45.41% <12.50%> (-0.01%) ⬇️
unit 36.56% <12.50%> (+0.13%) ⬆️

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.

Comment thread .changeset/css-modules-order-name.md Outdated

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

Adds a new CSS module ordering hook so plugins can override webpack’s default CSS import-order sort, with generated typings, release notes, and config-case coverage for ordering behaviors.

Changes:

  • Adds CssModulesPlugin.getCompilationHooks(compilation).orderModules.
  • Updates generated public typings and adds a minor changeset.
  • Adds CSS config cases for name ordering, priority ordering, fallback behavior, and SyncBailHook multi-tap behavior.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated no comments.

Show a summary per file
File Description
.changeset/css-modules-order-name.md Documents the new CSS ordering hook as a minor feature.
lib/css/CssModulesPlugin.js Defines and invokes the new orderModules hook during CSS module ordering.
types.d.ts Adds generated public typings for the new hook.
test/configCases/css/css-modules-order-fallback/a.css Fixture CSS module for fallback ordering test.
test/configCases/css/css-modules-order-fallback/b.css Fixture CSS module for fallback ordering test.
test/configCases/css/css-modules-order-fallback/c.css Fixture CSS module for fallback ordering test.
test/configCases/css/css-modules-order-fallback/d.css Fixture CSS module for fallback ordering test.
test/configCases/css/css-modules-order-fallback/e.css Fixture CSS module for fallback ordering test.
test/configCases/css/css-modules-order-fallback/index.js Asserts undefined hook result keeps default ordering.
test/configCases/css/css-modules-order-fallback/lazy1.css Fixture importing CSS in conflicting order.
test/configCases/css/css-modules-order-fallback/lazy2.css Fixture importing CSS in conflicting order.
test/configCases/css/css-modules-order-fallback/lazy3.css Fixture importing additional CSS.
test/configCases/css/css-modules-order-fallback/lazy4.js Fixture importing CSS through JS.
test/configCases/css/css-modules-order-fallback/test.config.js Selects bundles for fallback ordering test.
test/configCases/css/css-modules-order-fallback/warnings.js Asserts default conflict warning remains.
test/configCases/css/css-modules-order-fallback/webpack.config.js Adds plugin returning undefined from hook.
test/configCases/css/css-modules-order-multi-tap/a.css Fixture CSS module for multi-tap test.
test/configCases/css/css-modules-order-multi-tap/b.css Fixture CSS module for multi-tap test.
test/configCases/css/css-modules-order-multi-tap/c.css Fixture CSS module for multi-tap test.
test/configCases/css/css-modules-order-multi-tap/d.css Fixture CSS module for multi-tap test.
test/configCases/css/css-modules-order-multi-tap/e.css Fixture CSS module for multi-tap test.
test/configCases/css/css-modules-order-multi-tap/index.js Asserts first SyncBailHook result wins.
test/configCases/css/css-modules-order-multi-tap/lazy1.css Fixture importing CSS in conflicting order.
test/configCases/css/css-modules-order-multi-tap/lazy2.css Fixture importing CSS in conflicting order.
test/configCases/css/css-modules-order-multi-tap/lazy3.css Fixture importing additional CSS.
test/configCases/css/css-modules-order-multi-tap/lazy4.js Fixture importing CSS through JS.
test/configCases/css/css-modules-order-multi-tap/test.config.js Selects bundles for multi-tap test.
test/configCases/css/css-modules-order-multi-tap/webpack.config.js Adds two hook taps to verify bail behavior.
test/configCases/css/css-modules-order-name/a.css Fixture CSS module for name ordering test.
test/configCases/css/css-modules-order-name/b.css Fixture CSS module for name ordering test.
test/configCases/css/css-modules-order-name/c.css Fixture CSS module for name ordering test.
test/configCases/css/css-modules-order-name/d.css Fixture CSS module for name ordering test.
test/configCases/css/css-modules-order-name/e.css Fixture CSS module for name ordering test.
test/configCases/css/css-modules-order-name/index.js Asserts emitted CSS follows hook-provided name order.
test/configCases/css/css-modules-order-name/lazy1.css Fixture importing CSS in conflicting order.
test/configCases/css/css-modules-order-name/lazy2.css Fixture importing CSS in conflicting order.
test/configCases/css/css-modules-order-name/lazy3.css Fixture importing additional CSS.
test/configCases/css/css-modules-order-name/lazy4.js Fixture importing CSS through JS.
test/configCases/css/css-modules-order-name/test.config.js Selects bundles for name ordering test.
test/configCases/css/css-modules-order-name/webpack.config.js Adds plugin returning pre-sorted modules.
test/configCases/css/css-modules-order-priority/a.css Fixture CSS module for priority ordering test.
test/configCases/css/css-modules-order-priority/b.css Fixture CSS module for priority ordering test.
test/configCases/css/css-modules-order-priority/c.css Fixture CSS module for priority ordering test.
test/configCases/css/css-modules-order-priority/d.css Fixture CSS module for priority ordering test.
test/configCases/css/css-modules-order-priority/e.css Fixture CSS module pinned first by priority test.
test/configCases/css/css-modules-order-priority/index.js Asserts hook can pin e.css before other modules.
test/configCases/css/css-modules-order-priority/lazy1.css Fixture importing CSS in conflicting order.
test/configCases/css/css-modules-order-priority/lazy2.css Fixture importing CSS in conflicting order.
test/configCases/css/css-modules-order-priority/lazy3.css Fixture importing additional CSS.
test/configCases/css/css-modules-order-priority/lazy4.js Fixture importing CSS through JS.
test/configCases/css/css-modules-order-priority/test.config.js Selects bundles for priority ordering test.
test/configCases/css/css-modules-order-priority/webpack.config.js Adds plugin that prioritizes e.css.

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

@codspeed-hq

codspeed-hq Bot commented May 18, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 29.85%

❌ 1 regressed benchmark
✅ 143 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 "concatenate-modules", scenario '{"name":"mode-development","mode":"development"}' 780.1 KB 1,112 KB -29.85%

Tip

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


Comparing claude/solve-issue-20976-g8iYO (f528d02) with main (526d638)

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.

alexander-akait and others added 2 commits May 18, 2026 21:05
Co-authored-by: Kārlis Gaņģis <Knagis@users.noreply.github.com>
…ests

- Add JSDoc types (Compiler, Variant, CssCompilationHooks) so the file
  passes lint:types-test under TypeScript strict mode.
- Replace the Unix-only `endsWith("/e.css")` check in the "priority"
  variant with a cross-platform regex `/[\\/]e\.css$/` so the test also
  passes on windows-latest where module identifiers use backslashes.
@github-actions

Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging claude/solve-issue-20976-g8iYO into main will be
98.95%
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%37
   ChunkGraph.js100%100%100%100%
   ChunkGroup.js100%100%100%100%
   ChunkTemplate.js100%100%100%100%
   CleanPlugin.js98.72%100%100%98.72%206, 226, 382
   CodeGenerationResults.js100%100%100%100%
   CompatibilityPlugin.js100%100%100%100%
   Compilation.js98.55%100%100%98.55%1554, 1850, 1857, 1865, 1887, 2783, 3208, 3870, 3899, 3952–3953, 3957, 3962, 3978–3979, 3993–3994, 3999–4000, 4477, 4503, 493, 498, 5211, 5292, 5307, 5332–5333, 5335, 5659, 5664, 5670, 5673, 5685, 5687, 5691, 5707, 5722, 5754, 5808, 5832, 5946, 712–713
   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.js97.88%100%100%97.88%237, 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.96%100%100%98.96%424–428, 576
   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%
   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%1074, 1383, 473, 485
   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%134–135
   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.71%100%100%98.71%117, 469, 501, 543, 813
   index.js100%100%100%100%
   validateSchema.js94.67%100%100%94.67%100, 87, 89, 98
   webpack.js97.22%100%100%97.22%196, 218, 220
lib/asset
   AssetBytesGenerator.js100%100%100%100%
   AssetBytesParser.js100%100%100%100%
   AssetGenerator.js100%100%100%100%
   AssetModulesPlugin.js97.77%100%100%97.77%285, 309, 312, 364, 40
   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.18%100%100%99.18%1401–1403, 1411, 271, 274, 279, 283, 475
   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%
   HoistContainerReferencesPlugin.js100%100%100%100%
   ModuleFederationPlugin.js100%100%100%100%
   RemoteModule.js100%100%100%100%
   

@alexander-akait alexander-akait merged commit 561ee9b into main May 19, 2026
101 of 104 checks passed
@alexander-akait alexander-akait deleted the claude/solve-issue-20976-g8iYO branch May 19, 2026 12:49
alexander-akait pushed a commit to webpack/webpack.js.org that referenced this pull request May 19, 2026
…s() and orderModules (#8248)

Webpack 5.107 adds a new orderModules hook on
CssModulesPlugin.getCompilationHooks(compilation). It is a SyncBailHook
called once per CSS source type (CSS_IMPORT_TYPE and CSS_TYPE) with the
chunk's modules pre-sorted by full module name, letting plugin authors
override the default import-order topological sort and side-step the
"Conflicting order between css ..." warning.

Adds a new section at the end of compilation-hooks.mdx documenting both
the CssModulesPlugin.getCompilationHooks() entry point and the
orderModules hook itself, following the pattern already used in the
file for NormalModule.getCompilationHooks().loader.

Refs: webpack/webpack#20978
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.

3 participants