Skip to content

fix: render ProfilingPlugin trace in Chrome DevTools#21269

Merged
alexander-akait merged 8 commits into
mainfrom
fix/profiling-plugin-chrome-frames
Jun 26, 2026
Merged

fix: render ProfilingPlugin trace in Chrome DevTools#21269
alexander-akait merged 8 commits into
mainfrom
fix/profiling-plugin-chrome-frames

Conversation

@alexander-akait

@alexander-akait alexander-akait commented Jun 24, 2026

Copy link
Copy Markdown
Member

Summary

Closes #17234. ProfilingPlugin emitted the TracingStartedInBrowser event with only sessionId in args.data. Modern Chrome DevTools treats that as the primary trace-bootstrap event and iterates args.data.frames, so loading the generated events.json failed with frames is not iterable (Firefox's profiler is more lenient, which is why the same file still works there). This adds the frames array, mirroring the sibling TracingStartedInPage event.

What kind of change does this PR introduce?

fix

Did you add tests for your changes?

Yes — a fast deterministic assertion in test/configCases/plugins/profiling-plugin/index.js that replays Chrome DevTools' frame-bootstrap over the generated events.json, plus an optional real-browser end-to-end check in test/ProfilingPlugin.unittest.js that loads the trace in headless Chrome via puppeteer-core and self-skips when no Chrome (or an old Node/Bun/Deno runtime) is available.

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?

n/a

Use of AI

Yes. AI (Claude Code) assisted with the root-cause investigation against Chrome's trace-engine source, the fix, the tests, and this description. All changes were reviewed by me and verified by running the test suite.

@changeset-bot

changeset-bot Bot commented Jun 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e6247a4

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 Jun 24, 2026

Copy link
Copy Markdown
Contributor

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

Install it locally:

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

@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.86%. Comparing base (322b060) to head (e6247a4).

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #21269   +/-   ##
=======================================
  Coverage   92.85%   92.86%           
=======================================
  Files         592      592           
  Lines       65024    65024           
  Branches    18163    18163           
=======================================
+ Hits        60379    60382    +3     
+ Misses       4645     4642    -3     
Flag Coverage Δ
css-parsing 28.63% <ø> (ø)
html5lib 31.09% <ø> (ø)
integration 88.99% <ø> (-0.01%) ⬇️
test262 45.53% <ø> (-0.04%) ⬇️
unit 43.01% <ø> (+1.57%) ⬆️

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

☔ View full report in Codecov by Harness.
📢 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.

@codspeed-hq

codspeed-hq Bot commented Jun 24, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 3 improved benchmarks
❌ 3 regressed benchmarks
✅ 138 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Memory benchmark "many-modules-esm", scenario '{"name":"mode-development","mode":"development"}' 1.1 MB 1.9 MB -41.03%
Memory benchmark "wasm-modules-async", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 187.6 KB 247.7 KB -24.29%
Memory benchmark "devtool-eval-source-map", scenario '{"name":"mode-production","mode":"production"}' 6.4 MB 8.1 MB -20.91%
Memory benchmark "wasm-modules-sync", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 252.7 KB 132.8 KB +90.32%
Memory benchmark "asset-modules-inline", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 1,194.8 KB 800.9 KB +49.17%
Memory benchmark "json-modules", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 364.7 KB 280.5 KB +30.03%

Tip

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


Comparing fix/profiling-plugin-chrome-frames (e6247a4) with main (322b060)

Open in CodSpeed

@alexander-akait alexander-akait force-pushed the fix/profiling-plugin-chrome-frames branch from 6daa1a7 to 7c5d64c Compare June 24, 2026 16:30
Chrome DevTools' performance panel treats TracingStartedInBrowser as the
primary trace-bootstrap event and iterates args.data.frames. The plugin
emitted that event without a frames array, so loading the generated
events.json failed with "frames is not iterable". Add the frames array
(matching the sibling TracingStartedInPage event) so the trace loads.

Closes #17234
Launch headless Chrome and run DevTools' frame-bootstrap iteration over the
plugin-generated events.json. The test self-skips when puppeteer or a working
Chrome is unavailable.
puppeteer requires Node 18+ and its postinstall fails to parse on the Node
10.x/12.x install matrix, so it cannot be a committed devDependency. Drop it
from package.json, exclude the browser test from the types-test tsc pass, and
add a dedicated latest-LTS CI job that installs puppeteer on demand and runs
the test. The test self-skips wherever puppeteer or Chrome is unavailable.
…er-core

Replace the dedicated latest-LTS CI job with a committed puppeteer-core
devDependency (no postinstall, so it installs cleanly on the legacy-Node
matrix) and run the browser check in the unit suite instead of the
integration matrix. It launches the runner's installed Chrome and self-skips
when none is available or under the Bun/Deno runtimes.
Replace EXPECTED_ANY in the browser test with real puppeteer-core types
(Browser/LaunchOptions) and a typed trace-event shape, and skip when Node < 18
(puppeteer-core's minimum runtime). Document in AGENTS.md that specific real
types and generics are preferred over EXPECTED_ANY/OBJECT/FUNCTION.
Gate the require behind the same Node >= 18 / not-Bun-or-Deno check used to
run the test, so the heavy puppeteer-core module graph is never loaded into
the memory-limited Bun/Deno workers running the full suite.
@alexander-akait alexander-akait force-pushed the fix/profiling-plugin-chrome-frames branch from cb7e97a to 669d299 Compare June 25, 2026 19:46
Bun's Node `inspector` CPU profiler never resolves, so this test hung the
full Bun runtimes suite until its 120s timeout. It runs unchanged under Node,
where the V8 inspector is fully supported.
@github-actions

Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging fix/profiling-plugin-chrome-frames into main will be
99.36%
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/module-federation
   test.filter.js100%100%100%100%
examples/reexport-components
   test.filter.js100%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-emscripten
   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%
   CircularModulesPlugin.js98.81%100%100%98.81%136
   CleanPlugin.js99.15%100%100%99.15%207, 227
   CodeGenerationResults.js100%100%100%100%
   CompatibilityPlugin.js100%100%100%100%
   Compilation.js98.43%100%100%98.43%1641, 1960, 1967, 1975, 1997, 2000, 2940, 3419–3420, 3452, 4118, 4148, 4201–4202, 4206, 4211, 4227–4228, 4242–4243, 4248–4249, 4726, 4752, 526, 531, 5560, 5592, 5609, 5625, 5641, 5656, 5681–5682, 5684, 6012, 6017, 6023, 6026, 6038, 6040, 6044, 6060, 6075, 6107, 6161, 6185, 6299, 777–778
   Compiler.js99.56%100%100%99.56%1147–1148, 1156
   ConcatenationScope.js98.65%100%100%98.65%195
   ConditionalInitFragment.js100%100%100%100%
   ConstPlugin.js100%100%100%100%
   ContextExclusionPlugin.js100%100%100%100%
   ContextModule.js100%100%100%100%
   ContextModuleFactory.js97.40%100%100%97.40%258, 395, 418, 420, 424, 433–434
   ContextReplacementPlugin.js100%100%100%100%
   DefinePlugin.js99%100%100%99%171–172, 188, 207, 281
   DependenciesBlock.js100%100%100%100%
   Dependency.js98.51%100%100%98.51%479, 525
   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.50%100%100%98.50%1062, 1065, 450–454, 456, 602
   ExternalModuleFactoryPlugin.js100%100%100%100%
   ExternalsPlugin.js100%100%100%100%
   FileSystemInfo.js99.52%100%100%99.52%182, 2382–2383, 2386, 2397, 2408, 2419, 280, 3823, 3838, 3862
   FlagAllModulesAsUsedPlugin.js100%100%100%100%
   FlagDependencyExportsPlugin.js98.42%100%100%98.42%413, 422, 424, 428
   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%
   LazyBarrel.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%1285, 1290, 1350, 1364, 1426, 1435
   ModuleFactory.js100%100%100%100%
   ModuleFilenameHelpers.js98.85%100%100%98.85%106, 108
   ModuleGraph.js99.73%100%100%99.73%1005
   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%661
   MultiStats.js100%100%100%100%
   MultiWatching.js100%100%100%100%
   NoEmitOnErrorsPlugin.js100%100%100%100%
   NodeStuffPlugin.js100%100%100%100%
   NormalModule.js97.90%100%100%97.90%1237, 1240, 1257, 1274, 1521, 1555, 1571, 1658, 2014, 2313, 2318–2328, 418, 422, 576
   NormalModuleFactory.js99.47%100%100%99.47%1083, 1392, 486, 498
   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%527–528, 533, 535, 599
   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.js98.62%100%100%98.62%220, 224, 226, 419, 430, 889
   Stats.js100%100%100%100%
   Template.js100%100%100%100%
   TemplatedPathPlugin.js99.43%100%100%99.43%308–309
   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%371
   cli.js98.63%100%100%98.63%10, 119, 549, 581, 631, 905
   index.js99.72%100%100%99.72%184
   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%
   AssetModule.js100%100%100%100%
   AssetModulesPlugin.js97.33%100%100%97.33%282, 306, 309, 36, 362, 41
   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/bun
   BunTargetPlugin.js100%100%100%100%
lib/cache
   AddBuildDependenciesPlugin.js100%100%100%100%
   AddManagedPathsPlugin.js100%100%100%100%
   IdleFileCachePlugin.js97.92%100%100%97.92%75, 87, 95
   MemoryCachePlugin.js95.83%100%100%95.83%33
   MemoryWithGcCachePlugin.js93.15%100%100%93.15%107, 114–115, 123, 90
   PackFileCacheStrategy.js96.40%100%100%96.40%1251, 1351, 1355, 1417, 628, 647, 657–659, 661, 677–678, 683, 686, 688, 693, 698, 723, 729, 763, 769, 775, 780, 791, 800, 805–806, 808, 825, 831–832, 834
   ResolverCachePlugin.js100%100%100%100%
   getLazyHashedEtag.js100%100%100%100%
   mergeEtags.js100%100%100%100%
lib/config
   browserslistTargetHandler.js100%100%100%100%
   defaults.js99.33%100%100%99.33%1468–1470, 1478, 274,

@alexander-akait alexander-akait merged commit ed9fa71 into main Jun 26, 2026
63 checks passed
@alexander-akait alexander-akait deleted the fix/profiling-plugin-chrome-frames branch June 26, 2026 06:21
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.

ProfilingPlugin not rendering in Chrome

2 participants