Skip to content

fix(pack): isolate runtime public path for async chunks - #3391

Merged
fireairforce merged 2 commits into
nextfrom
zoomdong/fix-runtime-public-path
Sep 26, 2026
Merged

fireairforce merged 2 commits into
nextfrom
zoomdong/fix-runtime-public-path

Conversation

@fireairforce

@fireairforce fireairforce commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Use a runtime-local public path for __webpack_public_path__ reads and assignments.
  • Update the next.js submodule to the runtime change in utooland/next.js#195.
  • Add a browser runtime regression fixture and refresh affected snapshots.

Cause and fix

With output.publicPath: "runtime", a child application can overwrite the shared globalThis.publicPath after the host starts. The host previously read that global again when a later tab click loaded an async chunk, so it requested the host chunk from the child's CDN path and received a 404. The runtime now captures its own path at startup. Explicit __webpack_public_path__ assignments update that runtime's value without changing the shared global.

Compatibility note

This changes observable behavior for applications that intentionally modify globalThis.publicPath after the runtime starts to redirect later chunk requests. Set the global path before loading the runtime, or assign __webpack_public_path__ in application code to change the current runtime's path. An explicit __webpack_public_path__ assignment no longer writes globalThis.publicPath in any client public-path mode.

The auto and fixed-path modes continue to resolve chunk URLs as before. The __webpack_public_path__ read/write transform applies to those modes too, so its global side effect changes there as well. This PR addresses runtime isolation and async chunk URL behavior; it does not claim full Webpack public-path equivalence across all modes.

Verification

  • Before the fix, the new VM regression requested https://child.example/assets/... for the host's first async chunk.
  • After the fix, cargo test -p pack-tests --test snapshot -- --quiet passed: 149/149.
  • cargo fmt --check and cargo clippy --all-targets -- -D warnings --no-deps passed.

The next.js submodule now points to the merged utooland/next.js#195 commit (c1985d56d518f1c930f7fc5d7307e0eecaa5d453).

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-24T08:01:58.576660Z e3fd542 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

A child application can replace globalThis.publicPath after the host runtime starts. Keep the host chunk base in its own runtime and map __webpack_public_path__ assignments to that runtime-local value.
@fireairforce
fireairforce force-pushed the zoomdong/fix-runtime-public-path branch from e3fd542 to d82a7ff Compare September 24, 2026 08:01
@github-actions

Copy link
Copy Markdown

📊 Performance Benchmark Report (with-antd)

Utoopack Performance Report

Report ID: utoopack_performance_report_20260924_084050
Generated: 2026-09-24 08:40:50
Trace File: trace_antd.json (0.3GB, 0.83M spans)
Test Project: examples/with-antd


Executive Summary

Metric Value Assessment
Total Wall Time 6,482.8 ms Baseline
Total Thread Work (de-duped) 19,698.5 ms Non-overlapping busy time
Effective Parallelism 3.0x thread_work / wall_time
Working Threads 9 Threads with actual spans
Thread Utilization 33.8% ⚠️ Suboptimal
Total Spans 827,273 All B/E + X events
Meaningful Spans (>= 10us) 219,969 (26.6% of total)
Tracing Noise (< 10us) 607,304 (73.4% of total)

Build Phase Timeline

Shows when each build phase is active and how much CPU it consumes.
Self-Time is the time spent exclusively in that phase (excluding children).

Phase Spans Inclusive (ms) Self-Time (ms) Wall Range (ms)
Resolve 48,916 6,655.8 1,816.0 3,122.6
Parse 8,187 1,271.6 978.7 5,811.7
Analyze 141,584 43,134.0 8,846.3 5,709.9
Chunk 5,498 6,354.0 1,051.3 2,335.2
Codegen 12,608 2,353.2 1,492.7 2,004.9
Emit 31 27.8 13.9 7.0
Other 3,145 6,935.1 3,889.2 6,482.8

Workload Distribution by Diagnostic Tier

Category Spans Inclusive (ms) % Work Self-Time (ms) % Self
P0: Scheduling & Resolution 191,155 50,359.7 255.7% 10,902.2 55.3%
P1: I/O & Heavy Tasks 2,729 78.5 0.4% 64.7 0.3%
P2: Architecture (Locks/Memory) 0 0.0 0.0% 0.0 0.0%
P3: Asset Pipeline 24,926 10,041.1 51.0% 3,568.9 18.1%
P4: Bridge/Interop 0 0.0 0.0% 0.0 0.0%
Other 1,159 6,252.2 31.7% 3,552.4 18.0%

Top 20 Tasks by Self-Time

Self-time is the exclusive duration: time spent in the task itself, not in sub-tasks.
This is the most accurate indicator of where CPU cycles are actually spent.

Self (ms) Inclusive (ms) Count Avg Self (us) P95 Self (ms) Max Self (ms) % Work Task Name Top Caller
4,401.3 25,199.1 95,276 46.2 0.1 9.2 22.3% module module (61%)
2,416.3 2,588.9 15 161084.3 359.0 463.9 12.3% save snapshot persist (7%)
2,072.9 2,196.4 2,433 852.0 2.6 289.0 10.5% analyze ecmascript module module (72%)
1,477.7 14,594.4 34,009 43.5 0.1 9.1 7.5% process module process module (82%)
1,216.1 3,246.1 26,692 45.6 0.1 7.1 6.2% internal resolving internal resolving (77%)
936.5 6,078.9 4,096 228.6 0.3 138.8 4.8% chunking chunking (43%)
935.0 1,227.9 6,017 155.4 0.6 38.6 4.7% parse ecmascript parse ecmascript (65%)
837.7 922.1 10,315 81.2 0.3 8.4 4.3% precompute code generation generate merged code (39%)
751.6 887.1 7,173 104.8 0.4 118.9 3.8% compute async module info compute async module info (57%)
592.9 3,402.6 21,696 27.3 0.0 4.1 3.0% resolving module (55%)
588.3 2,040.8 885 664.7 1.6 219.4 3.0% generate merged code chunking (52%)
444.8 444.8 329 1352.0 1.7 255.8 2.3% generate source map code generation (83%)
340.6 773.0 129 2640.5 4.2 199.5 1.7% emit code emit code (53%)
303.1 562.9 1,570 193.1 0.1 149.9 1.5% write all entrypoints to disk write all entrypoints to disk (18%)
210.1 986.2 1,964 107.0 0.3 48.6 1.1% code generation code generation (83%)
175.1 175.1 7 25018.9 113.3 154.7 0.9% blocking save snapshot (57%)
111.1 271.0 1,335 83.2 0.1 11.5 0.6% compute async chunks compute async chunks (41%)
89.9 106.0 803 112.0 0.0 29.2 0.5% compute binding usage info compute binding usage info (45%)
43.7 43.7 2,168 20.1 0.0 0.3 0.2% read file parse ecmascript (92%)
39.8 70.6 1,870 21.3 0.0 14.4 0.2% collect mergeable modules collect mergeable modules (100%)

Critical Path Analysis

The longest sequential dependency chains that determine wall-clock time.
Focus on reducing the depth of these chains to improve parallelism.

Rank Self-Time (ms) Depth Path
1 618.6 3 persist → save snapshot → blocking
2 422.5 6 chunking → generate merged code → emit code → emit code → emit code → read file
3 296.7 4 chunking → generate merged code → emit code → generate source map
4 289.8 10 module → module → module → ... → process module → analyze ecmascript module → analyze ecmascript module
5 204.0 8 module → module → process module → process module → process module → process module → process module → analyze ecmascript module

Batching Candidates

High-volume tasks dominated by a single parent. If the parent can batch them,
it drastically reduces scheduler overhead.

Task Name Count Top Caller (Attribution) Avg Self P95 Self Total Self
process module 34,009 process module (82%) 43.5 us 0.07 ms 1,477.7 ms
internal resolving 26,692 internal resolving (77%) 45.6 us 0.09 ms 1,216.1 ms

Duration Distribution

Range Count Percentage
<10us 607,304 73.4%
10us-100us 143,481 17.3%
100us-1ms 65,406 7.9%
1ms-10ms 10,870 1.3%
10ms-100ms 163 0.0%
>100ms 49 0.0%

Action Items

  1. [P0] Focus on tasks with the highest Self-Time — these are where CPU cycles are actually spent.
  2. [P0] Use Batching Candidates to identify callers that should use try_join or reduce #[turbo_tasks::function] granularity.
  3. [P1] Check Build Phase Timeline for phases with disproportionate wall range vs. self-time (= serialization).
  4. [P1] Inspect P95 Self (ms) for heavy monolith tasks. Focus on long-tail outliers, not averages.
  5. [P1] Review Critical Paths — reducing the longest chain depth directly improves wall-clock time.
  6. [P2] If Thread Utilization < 60%, investigate scheduling gaps (lock contention or deep dependency chains).

Report generated by Utoopack Performance Analysis Agent

@PeachScript PeachScript 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.

+1

@fireairforce
fireairforce merged commit 69376d5 into next Sep 26, 2026
92 of 103 checks passed
@fireairforce
fireairforce deleted the zoomdong/fix-runtime-public-path branch September 26, 2026 09:38
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