fix: skip unchanged native stylesheet reinitialization - #652
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review. 📝 WalkthroughWalkthroughNative Metro bundles now compute SHA-256 fingerprints from compiled CSS and themes. Native development configuration skips reinitialization for unchanged fingerprints and retries after failures. Tests cover unchanged, changed, and failed initialization cases. ChangesNative style fingerprinting
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: 🔵 Low · up to The change reduces unnecessary native stylesheet refresh work during development, but a partially failed refresh could leave theme and style-store state inconsistent and cause a later rollback to be skipped. The PR is mergeable with explicit owner awareness or follow-up coverage for this recovery path. Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant MetroTransformer
participant NativeBundle
participant UniwindConfig
participant StyleStore
MetroTransformer->>MetroTransformer: Hash compiled CSS and themes
MetroTransformer->>NativeBundle: Emit __reinit with fingerprint
NativeBundle->>UniwindConfig: Call __reinit
UniwindConfig->>StyleStore: Initialize styles when fingerprint changed
UniwindConfig-->>NativeBundle: Skip unchanged development initialization
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Full details: Docstring CoverageExplanation No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3 files. (1 skipped: 1 unsupported.) ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThe PR fingerprints generated native stylesheet data and theme names so development Fast Refresh can avoid rebuilding unchanged style state. Major changes:
Confidence Score: 5/5The PR appears safe to merge with no actionable correctness or security issues identified. The fingerprint covers all state consumed by native stylesheet initialization, is checked only after a successful prior initialization, and preserves retry and unfingerprinted-call behavior.
|
| Filename | Overview |
|---|---|
| packages/uniwind/src/bundler/adapters/metro/transformer.ts | Hashes the complete generated native initialization inputs and embeds the fingerprint in the generated module. |
| packages/uniwind/src/core/config/config.native.ts | Adds a development-only equality guard and commits the fingerprint only after successful initialization. |
| packages/uniwind/tests/native/core/config.test.ts | Covers unchanged and changed fingerprints as well as retry behavior following an initialization exception. |
| CONTEXT.md | Documents fingerprint-based native stylesheet reinitialization behavior. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Metro compiles native CSS] --> B[Hash generated styles and themes]
B --> C[Call Uniwind.__reinit]
C --> D{Development fingerprint matches?}
D -->|Yes| E[Skip stylesheet rebuild]
D -->|No| F[Update configured themes]
F --> G[Reinitialize native style store]
G --> H[Store fingerprint after success]
Reviews (1): Last reviewed commit: "fix: skip unchanged native stylesheet re..." | Re-trigger Greptile
|
🚀 This pull request is included in v1.12.0. See Release v1.12.0 for release notes. |
Note
The following is agent reported but I got approval from Hubert to file this so hope you don't mind:

We found this while profiling slow Fast Refresh in T3 Code Mobile with Hermes CPU samples and React timing traces against a populated environment.
A comment-only edit to an unmounted screen caused Uniwind to reinitialize the native stylesheet, clear style caches, and call
notifyAll(), even though the generated styles hadn't changed. That made unrelated mounted components do work. Instrumenting__reinitand temporarily bypassing it for that edit confirmed the source of the extra work.This patch fingerprints the generated native stylesheet and theme list in the Metro transformer. In development,
__reinitskips reinitialization when the fingerprint matches the last successful initialization.CSS compilation and class discovery still run. Hashing the generated output matters because edits to component files can introduce new Tailwind classes without changing the CSS source.
For the comparison, we used the same patched build and toggled only the fingerprint guard. The control omitted the fingerprint argument; the treatment supplied it. Measurements cover the same two-second window around a comment-only edit.
That's approximately 43% less sampled JS work on Home and 59% less on the large thread.
These were individual matched simulator runs using Expo 57.0.18, React Native 0.86.3, and Uniwind 1.7.0 on an iPhone 17 Pro simulator running iOS 26.5. They measure work around the edit, not end-to-end Fast Refresh latency.
We subsequently rebased and verified the patch on Uniwind 1.11.0:
Changed styles or theme lists still initialize normally. The fingerprint is stored only after initialization succeeds, allowing failed initialization to retry. Calls without a fingerprint, production initialization, and the web path retain their existing behavior.
Summary by CodeRabbit
Performance
Bug Fixes
Documentation