Repository navigation
fix(metro): skip the generated uniwind.css when tracking imported CSS - #720
Draft
dlebedynskyi wants to merge 1 commit into
Draft
dlebedynskyi wants to merge 1 commit into
dlebedynskyi wants to merge 1 commit into
Conversation
Since uni-stack#676, development native entries require every stylesheet Tailwind reports that isn't under node_modules. When uniwind is linked (a workspace package, `npm link`, a `file:` install), Tailwind resolves `@import 'uniwind'` to the package's uniwind.css by its real path, outside node_modules. The entry then requires the artifact that its own transform rewrites. Every write changes a module in Metro's graph and re-runs the uncached entry transform. A single server rebuilds the entry once more at startup, and two Metro servers with different theme lists rewrite the artifact for each other indefinitely. Leave out the stylesheet whose real path is the generated artifact's. Local stylesheets and linked workspace stylesheets are still required.
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
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 |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I ran into this in a monorepo where uniwind is a workspace package. After #676, two apps' Metro dev servers running at the same time kept rebuilding each other, because each entry now watched the generated
uniwind.cssthat the other server kept rewriting. Clode did the most of the work bellow.This follows up #676. When uniwind is linked instead of installed, the native development entry requires
uniwind.css. That's the file the entry's own transform rewrites. Linked setups include a workspace package (like the examples in this repo),npm link, or afile:dependency. If two Metro servers with different theme lists run at once, each one's writes rebuild the other, and it never stops.On
main(9fc9b40), I added anhmr-tokens.cssimport toapps/expo-example/global.cssand fetched the iOS dev bundle. These are the stylesheets the CSS entry module depends on:global.css -> ["hmr-tokens.css", "../../packages/uniwind/uniwind.css"]apps/barebehaves the same way:src/global.css -> ["src/hmr-tokens.css", "../../packages/uniwind/uniwind.css"].Next I ran
apps/expo-example(light, dark, premium) alongside a copy of it with one extra theme (extraThemes: ['premium', 'ocean']). Each ranexpo startfrom its own directory, with an HMR client registered for its iOS bundle. I counted the HMR updates that carried modules and the writes topackages/uniwind/uniwind.css:uniwind.csswritesThis keeps going until one of the servers stops. Each rebuild runs the Tailwind compile for the entry again.
A single server pays once. On a fresh install the shipped artifact doesn't match the app's themes (
expo-exampleaddspremium), so the first transform rewrites it. When the HMR client connects, Metro handles that change and transforms the entry a second time.Cause
#676 requires every stylesheet Tailwind reports through
onDependencythat ends in.cssand isn't undernode_modules. Tailwind's resolver follows symlinks. So whennode_modules/uniwindis a link,@import 'uniwind'is reported by its real path,packages/uniwind/uniwind.css, and that passes the filter. It's the same filegenerateArtifacts(cssArtifactPath)writes at the start of the transform.Once the artifact is a module in the graph, Metro handles every write to it as a change, and the uncached entry gets transformed again, which regenerates the artifact. With one theme list, the second write has identical content and is skipped. With two servers, each writes its own themes, which the other sees as a change.
Fix
isImportedStylesheetkeeps the existing rules and also drops the stylesheet whose real path matches the generated artifact's. Both sides are resolved, so the check still works when the artifact path itself goes through a link. Local stylesheets and those of linked workspace packages are still required, so token edits still hot reload. I also added a line about this toCONTEXT.md.Testing
tests/native/bundler/transformer.test.tssets up a linked layout in a temporary directory:node_modules/uniwindandnode_modules/brandlink intopackages/, next to a regularnode_modules/theme. It compiles an entry that imports all three plus a localtokens.csswith Tailwind, then checks which reported stylesheets the entry keeps (tokens.cssandbrand.css). It covers the artifact path given as a real path and as a path through the link. With the old filter, both cases fail because they keeppackages/uniwind/uniwind.css. A plain string comparison passes the real-path case but fails the linked one.hmr-tokens.css.bun run test(native 205, web 48, e2e 9, types). I also exportedapps/expo-examplefor iOS, Android and web, builtapps/vite-example, and bundledapps/bare.For the two-server run I used a second Expo app, not
apps/bare. The bare app's React Native CLI runs its own Metro 0.84, while uniwind patches the root Metro 0.85, so Metro doesn't re-run the bare entry on file changes. Withapps/expo-exampleandapps/baretogether, the artifact was written three times at startup, each server rebuilt once, and then it stopped. The bare entry still requires the artifact.Who's affected
This affects native development builds with Metro where uniwind resolves outside
node_modules:workspace:*, as in this repo)npm link, or afile:/link:dependency that's installed as a symlinkRegular installs aren't affected because Tailwind reports a path under
node_modules, and that includes pnpm'snode_modules/.pnpm. Production builds and web don't add these requires, so they aren't affected either.The endless rebuilds need two or more Metro servers that share one uniwind copy and use different theme lists, for example two apps in the same monorepo. A single server transforms its entry one extra time at startup whenever the installed artifact doesn't match its themes.