Skip to content

feat(pack): Support auto public path in UtooPack#2953

Merged
xusd320 merged 2 commits into
nextfrom
xusd320/utoopack-public-path-auto
May 25, 2026
Merged

feat(pack): Support auto public path in UtooPack#2953
xusd320 merged 2 commits into
nextfrom
xusd320/utoopack-public-path-auto

Conversation

@xusd320
Copy link
Copy Markdown
Contributor

@xusd320 xusd320 commented May 15, 2026

Summary

  • add UtooPack support for output.publicPath: "auto"
  • map the new config value to a Turbopack runtime marker and avoid treating it as a literal dev/HTML prefix
  • add a public_path/auto snapshot fixture and refresh affected runtime snapshots
  • update the next.js submodule pointer to include the Turbopack runtime support from feat(turbopack): Support auto public path in Turbopack runtime next.js#149

Why

The existing default publicPath behavior resolves to /, while publicPath: "runtime" reads globalThis.publicPath. This adds a webpack-compatible "auto" mode for deployments where chunks and assets should resolve relative to the current runtime script URL.

Validation

  • cargo run -p pack-schema
  • UPDATE=1 cargo test -p pack-tests public_path -- --nocapture
  • cargo test -p pack-tests public_path -- --nocapture
  • npm run build --workspace @utoo/pack-shared
  • npm run build:js --workspace @utoo/pack
  • cargo fmt
  • cargo clippy --all-targets -- -D warnings --no-deps
  • git diff --check
  • git -C next.js diff --check

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request implements an 'auto' public path feature, which enables the runtime to automatically determine the base URL for assets based on the source of the executing script. The changes span the core configuration logic in Rust, the TypeScript build plugins, and the ECMAScript runtime. Feedback from the review points out that the string matching for the 'runtime' and 'auto' configuration keywords should be improved to handle trailing slashes, ensuring that user-provided values like 'auto/' are correctly identified as special modes rather than literal paths.

Comment on lines +1672 to 1676
match public_path.as_str() {
"runtime" => return Ok(Vc::cell("__RUNTIME_PUBLIC_PATH__".into())),
"auto" => return Ok(Vc::cell("__AUTO_PUBLIC_PATH__".into())),
_ => {}
}
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.

medium

The current implementation of computed_public_path handles the special values "runtime" and "auto" before enforcing a trailing slash. This is correct as these are internal markers. However, if a user provides "auto/" or "runtime/" in their configuration, they will fall through to the default case and be returned as literal paths with a trailing slash (e.g., "auto/"), which is likely not the intended behavior. Consider normalizing the input by trimming trailing slashes before matching against these keywords to be more resilient to user input.

Comment on lines +6 to +10
function normalizeHtmlPublicPath(globalPublicPath: string | undefined): string {
return globalPublicPath === "runtime" || globalPublicPath === "auto"
? ""
: (globalPublicPath ?? "");
}
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.

medium

The normalizeHtmlPublicPath function correctly returns an empty string for "runtime" and "auto" modes, which is appropriate for static HTML injection where assets are typically co-located. However, similar to the Rust implementation, it only matches exact strings. If a user provides "auto/" in their configuration, it will return "auto/", leading to broken URLs like auto//main.js during asset injection. Consider using a more robust check or normalizing the input string.

References
  1. Ensure that configuration keywords are handled consistently and resiliently across different parts of the codebase. (link)

@xusd320 xusd320 changed the title [codex] Support auto public path in UtooPack feat(pack): Support auto public path in UtooPack May 18, 2026
@xusd320 xusd320 marked this pull request as ready for review May 18, 2026 04:27
@xusd320 xusd320 force-pushed the xusd320/utoopack-public-path-auto branch from 986d25c to a30d96e Compare May 25, 2026 03:39
@github-actions
Copy link
Copy Markdown

📊 Performance Benchmark Report (with-antd)

Utoopack Performance Report

Report ID: utoopack_performance_report_20260525_065331
Generated: 2026-05-25 06:53:31
Trace File: trace_antd.json (0.5GB, 1.49M spans)
Test Project: examples/with-antd


Executive Summary

Metric Value Assessment
Total Wall Time 6,012.4 ms Baseline
Total Thread Work (de-duped) 19,563.4 ms Non-overlapping busy time
Effective Parallelism 3.3x thread_work / wall_time
Working Threads 5 Threads with actual spans
Thread Utilization 65.1% 🆗 Average
Total Spans 1,486,434 All B/E + X events
Meaningful Spans (>= 10us) 338,911 (22.8% of total)
Tracing Noise (< 10us) 1,147,523 (77.2% 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 75,787 2,088.8 1,664.1 3,537.6
Parse 8,630 1,157.9 1,094.0 5,897.0
Analyze 201,630 11,727.5 8,081.7 5,620.4
Chunk 18,341 1,599.5 1,493.4 1,764.1
Codegen 27,154 3,569.5 2,658.7 1,623.9
Emit 14 34.6 17.3 17.5
Other 7,355 880.4 721.1 6,012.4

Workload Distribution by Diagnostic Tier

Category Spans Inclusive (ms) % Work Self-Time (ms) % Self
P0: Scheduling & Resolution 283,227 14,587.4 74.6% 10,367.1 53.0%
P1: I/O & Heavy Tasks 2,893 107.6 0.5% 90.2 0.5%
P2: Architecture (Locks/Memory) 0 0.0 0.0% 0.0 0.0%
P3: Asset Pipeline 52,710 6,316.3 32.3% 5,235.5 26.8%
P4: Bridge/Interop 0 0.0 0.0% 0.0 0.0%
Other 81 46.9 0.2% 37.5 0.2%

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,334.4 6,260.9 131,694 32.9 0.1 13.4 22.2% module write all entrypoints to disk (1%)
2,056.8 2,076.1 26,435 77.8 0.2 207.2 10.5% analyze ecmascript module module (68%)
1,570.4 2,481.1 15,846 99.1 0.4 43.7 8.0% code generation chunking (1%)
1,051.6 1,135.4 10,261 102.5 0.2 67.7 5.4% chunking write all entrypoints to disk (0%)
1,027.9 1,091.8 6,414 160.3 0.6 39.9 5.3% parse ecmascript process module (32%)
976.2 1,063.8 42,342 23.1 0.0 8.7 5.0% internal resolving resolving (28%)
967.5 2,643.6 36,237 26.7 0.0 4.0 4.9% process module module (13%)
785.8 785.8 9,316 84.4 0.3 7.0 4.0% precompute code generation code generation (57%)
681.1 1,018.1 32,782 20.8 0.0 6.0 3.5% resolving module (11%)
666.3 805.4 6,883 96.8 0.0 104.3 3.4% write all entrypoints to disk None (0%)
636.0 636.0 5,802 109.6 0.4 69.6 3.3% compute async module info chunking (0%)
425.5 425.8 8,006 53.1 0.0 34.5 2.2% compute async chunks write all entrypoints to disk (0%)
302.6 302.6 1,992 151.9 0.4 22.9 1.5% generate source map code generation (97%)
66.0 66.0 2,215 29.8 0.0 3.1 0.3% read file parse ecmascript (92%)
55.4 55.4 801 69.2 0.0 14.0 0.3% compute binding usage info write all entrypoints to disk (0%)
20.3 20.3 646 31.4 0.0 4.7 0.1% collect mergeable modules compute merged modules (0%)
17.3 28.1 391 44.2 0.1 2.5 0.1% async reference write all entrypoints to disk (1%)
17.2 17.2 13 1319.6 5.8 6.2 0.1% write file apply effects (100%)
16.4 38.3 74 221.5 0.3 12.1 0.1% make production chunks chunking (5%)
14.1 14.1 4 3529.2 9.2 10.1 0.1% blocking map chunk groups (25%)

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 207.2 2 process module → analyze ecmascript module
2 60.2 2 code generation → generate source map
3 50.2 2 code generation → generate source map
4 47.2 2 module → analyze ecmascript module
5 39.9 2 process module → parse ecmascript

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
No obvious batching candidates found - - - - -

Duration Distribution

Range Count Percentage
<10us 1,147,523 77.2%
10us-100us 318,501 21.4%
100us-1ms 17,054 1.1%
1ms-10ms 3,266 0.2%
10ms-100ms 87 0.0%
>100ms 3 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

@xusd320 xusd320 requested review from fireairforce and yuzheng14 May 25, 2026 07:29
@xusd320 xusd320 merged commit feb3211 into next May 25, 2026
33 checks passed
@xusd320 xusd320 deleted the xusd320/utoopack-public-path-auto branch May 25, 2026 08:25
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