Skip to content

feat(pack): rewrite style-loader in Rust#2658

Open
Copilot wants to merge 9 commits intonextfrom
copilot/refactor-style-loader-rust
Open

feat(pack): rewrite style-loader in Rust#2658
Copilot wants to merge 9 commits intonextfrom
copilot/refactor-style-loader-rust

Conversation

Copy link
Contributor

Copilot AI commented Mar 3, 2026

Rewrites the @utoo/style-loader entirely in Rust as a native Turbopack CustomModuleType, replacing the previous JS webpack loader approach.

Changes Made

  • InlineCssModuleType: New Rust implementation of CustomModuleType trait that transforms CSS files into JavaScript modules injecting styles into the DOM at runtime
  • InlineCssFileSource: Generates JS wrapper code around CSS content, supporting multiple injection strategies (Style, SingletonStyle, Link, LazyStyle, LazySingletonStyle)
  • Runtime JS: Embedded runtime files at crates/pack-core/js/src/inline_css/ (referencing webpack style-loader) for <style> and <link> tag injection
  • Module rule wiring: Inline CSS module rule integrated in client/transforms.rs
  • Cleanup: Removed the old style_loader.rs webpack rules module and @utoo/style-loader from the import map, as inline CSS is now handled natively without webpack loader infrastructure
  • Snapshot test: Added crates/pack-tests/tests/snapshot/style/inline_css/ test case validating that CSS imports are correctly transformed into JS modules with embedded style injection via the injectStylesIntoStyleTag runtime
Original prompt

This section details on the original issue you should resolve

<issue_title>[Utoo Pack]: refactor style-loader</issue_title>
<issue_description>### Problem

  1. Maybe need to change style-loader to a pitch loader;
  2. provide more info like "sourcemap" to loader-runner
  3. impl with rust instead of js

Solution

Need more Investigations.

Alternatives

No response

Importance

nice to have

Additional Information

No response</issue_description>

<agent_instructions>Address this:

  1. reference the original https://github.com/webpack/style-loader, we use it to inline css to the javascript chunks
  2. currently, we use the @utoo/style-loader in crates/pack-core/src/shared/webpack_rules/style_loader.rs
  3. we need completely rewrite the @utoo/style-loader by rust</agent_instructions>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 3 commits March 3, 2026 16:36
Replaces the JS webpack loader (@utoo/style-loader) with a native Rust
implementation using Turbopack's CustomModuleType pattern.

- Create InlineCssModuleType and InlineCssFileSource in transforms/inline_css/
- Move runtime JS files to embedded filesystem (crates/pack-core/js/src/style-loader/)
- Register inline CSS module rule in client transforms
- Remove @utoo/style-loader from webpack rules and import map

Co-authored-by: xusd320 <16577489+xusd320@users.noreply.github.com>
Co-authored-by: xusd320 <16577489+xusd320@users.noreply.github.com>
Co-authored-by: xusd320 <16577489+xusd320@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor style-loader implementation with Rust feat(pack): rewrite style-loader in Rust Mar 3, 2026
@xusd320
Copy link
Contributor

xusd320 commented Mar 3, 2026

@copilot fix all CI

The `process` method on `ModuleAssetContext` comes from the `AssetContext`
trait, which needs to be in scope.

Co-authored-by: xusd320 <16577489+xusd320@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 3, 2026

@copilot fix all CI

Fixed in 539c3cd. All CI failures were caused by a missing use turbopack_core::context::AssetContext import in inline_css/module.rs — the process method on ModuleAssetContext comes from that trait.

@xusd320
Copy link
Contributor

xusd320 commented Mar 3, 2026

@copilot fix all CI again

…t_names

Co-authored-by: xusd320 <16577489+xusd320@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 3, 2026

@copilot fix all CI again

Fixed in ad4376c. Two clippy errors:

  1. collapsible_if in transforms.rs:37 — collapsed the nested if let into a single if let ... && let ...
  2. enum_variant_names in module.rs:29 — renamed InjectType variants to remove the common Tag postfix (StyleTagStyle, LinkTagLink, etc.)

@xusd320
Copy link
Contributor

xusd320 commented Mar 4, 2026

@copilot rename the folder crates/pack-core/js/src/style-loader to crates/pack-core/js/src/inline_css, add document comments to explain that is referencing to https://webpack.js.org/loaders/style-loader/

…mments

Co-authored-by: xusd320 <16577489+xusd320@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 4, 2026

@copilot rename the folder crates/pack-core/js/src/style-loader to crates/pack-core/js/src/inline_css, add document comments to explain that is referencing to https://webpack.js.or...

Done in d5ed0b9. Renamed js/src/style-loader/js/src/inline_css/, updated all Rust import paths (@utoo/pack-runtime/inline_css/...), and added doc comments referencing https://webpack.js.org/loaders/style-loader/ on the JS runtime files and the inline_css Rust module.

Co-authored-by: xusd320 <16577489+xusd320@users.noreply.github.com>
@xusd320
Copy link
Contributor

xusd320 commented Mar 4, 2026

@copilot add a test case in crates/pack-tests/tests for current refactoring

Co-authored-by: xusd320 <16577489+xusd320@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 4, 2026

@copilot add a test case in crates/pack-tests/tests for current refactoring

Added in 77f289f. Created crates/pack-tests/tests/snapshot/style/inline_css/ with a CSS file import test case (styles.inlineCss: {} config). The generated output confirms CSS content is embedded in JS via the injectStylesIntoStyleTag runtime.

@xusd320 xusd320 marked this pull request as ready for review March 4, 2026 05:57
@github-actions
Copy link

github-actions bot commented Mar 4, 2026

📊 Performance Benchmark Report (with-antd)

Utoopack Performance Report (Intelligent)

Report ID: utoopack_performance_report_20260304_061340
Generated: 2026-03-04 06:13:40
Trace File: trace_antd.json (0.5GB, 3.18M events)
Test Project: examples/with-antd


Executive Summary

Key Findings

Metric Value Assessment
Total Wall Time 7,899.2 ms Baseline
Total Thread Work (de-duped) 24,606.6 ms Non-overlapping busy time
Effective Parallelism 3.1x thread_work / wall_time
Working Threads 5 Threads with actual spans
Thread Utilization 62.3% 🆗 Average
Total Spans 1,590,185 All B/E + X events
Meaningful Spans (>= 10us) 505,567 (31.8% of total)
Tracing Noise (< 10us) 1,084,618 (68.2% of total)

Workload Distribution by Tier

Category Tasks Total Time (ms) % of Thread Work
P0: Runtime/Resolution 0 0.0 0.0%
P1: I/O & Heavy Tasks 38,122 3,517.2 14.3%
P3: Asset Pipeline 29,279 3,184.5 12.9%
P4: Bridge/Interop 0 0.0 0.0%
Other 438,166 19,969.8 81.2%

🤖 AI Intelligent Attributions

New section mapping granular tasks to bottlenecks.

Top 10 Batching Candidates

These highly-called tasks are dominated by a single parent. If the parent can batch them into one call, it drastically reduces scheduler overhead.

Task Name Count Top Caller (Attribution) Avg P95 Total Time
analyze ecmascript module 35,230 process module (77%) 97.7 us 0.28 ms 3,443.3 ms

Top 20 Tasks by Total Duration

Total (ms) Count Avg (us) P95 (ms) Max (ms) % Work Task Name Top Caller
7,349.3 181,308 40.5 0.1 9.9 29.9% module None (0%)
3,837.9 68,746 55.8 0.1 202.3 15.6% process module module (14%)
3,443.3 35,230 97.7 0.3 202.2 14.0% analyze ecmascript module process module (77%)
2,760.6 24,431 113.0 0.4 61.6 11.2% code generation chunking (7%)
1,623.1 57,053 28.4 0.0 16.1 6.6% resolving module (30%)
1,611.6 61,008 26.4 0.0 6.9 6.5% internal resolving resolving (31%)
1,286.9 29,315 43.9 0.1 7.7 5.2% precompute code generation code generation (34%)
1,261.3 14,325 88.0 0.2 45.0 5.1% chunking compute async chunks (0%)
1,179.2 13,102 90.0 0.4 129.5 4.8% compute async module info chunking (0%)
1,045.8 8,020 130.4 0.5 79.5 4.3% parse ecmascript analyze ecmascript module (26%)
492.3 4,884 100.8 0.1 48.1 2.0% compute async chunks compute async chunks (0%)
306.8 1,936 158.5 0.4 18.3 1.2% generate source map code generation (96%)
87.3 1,855 47.1 0.0 20.6 0.4% collect mergeable modules compute merged modules (0%)
66.9 656 101.9 0.0 18.0 0.3% compute binding usage info None (0%)
64.6 2,165 29.8 0.0 1.9 0.3% read file parse ecmascript (91%)
62.8 108 581.8 1.4 22.4 0.3% make production chunks chunking (6%)
37.9 8 4738.9 19.1 22.4 0.2% compute merged modules make production chunks (100%)
33.7 14 2410.5 9.1 9.3 0.1% apply effects None (0%)
33.1 13 2544.0 9.0 9.3 0.1% write file apply effects (100%)
23.3 576 40.4 0.1 2.5 0.1% async reference None (0%)

Duration Distribution

Range Count Percentage
< 10us (noise) 1,084,618 68.2%
10us - 100us 480,689 30.2%
100us - 1ms 20,786 1.3%
1ms - 10ms 4,017 0.3%
10ms - 100ms 72 0.0%
> 100ms 3 0.0%

Action Items

  1. [P0] Use Batching Candidates to pinpoint specific files needing try_join or reduced #[turbo_tasks::function] limits.
  2. [P1] Inspect P95 (ms) for heavy monolith tasks. Focus on long-tail outliers rather than averages.

Report generated by Intelligent Utoopack Performance Analysis Agent

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.

[Utoo Pack]: refactor style-loader

2 participants