Skip to content

[unplugin] stop loading imports from transform - #1941

Open
Om-singhaI wants to merge 2 commits into
meta:mainfrom
Om-singhaI:unplugin-no-import-walk
Open

Om-singhaI wants to merge 2 commits into
meta:mainfrom
Om-singhaI:unplugin-no-import-walk

Conversation

@Om-singhaI

Copy link
Copy Markdown
Contributor

What changed / motivation ?

In watch mode, which includes the Vite dev server, transform in core.js parsed its own output and awaited this.load() on every import before returning. Loading an import can itself wait on this transform, so in some setups it never returns:

The walk also never found what it was looking for. It read meta.stylex from each loaded import, but transform never returned meta. shouldTransformCachedModule reads the same field, so it did nothing either. On a cold Vite 7 load of a 300 component app the walk also caused 909 transforms of prebundled dependencies, against 7 without it.

  • Removed the walk.
  • transform now returns meta: { stylex: rules }, so shouldTransformCachedModule can restore a cached module's rules. That hook now skips runtimeInjection builds like transform does, and ignores meta without a stylex array.
  • Added two tests: a watch mode context whose load() never resolves, and a cached module whose rules come back from its meta.

Linked PR/Issues

Fixes #1912

Additional Context

Tests, on Node 25.6.1 and jest 30.1.3 from packages/@stylexjs/unplugin:

  • npx jest: 2 suites, 26 tests passed.
  • With src/core.js restored from main and the new tests kept, both new tests fail. The first times out after 1 s and the second gets '' for the CSS.
  • prettier and eslint are clean on both files. core.js has no @flow pragma.

I also built the plugin from main and from this branch into small apps on @stylexjs/stylex 0.19.1:

case main this branch
Vite 5.4.21, vite --force, the repro from #1912 no response after 15 s 200 in 0.03 s
Vite 7.3.7 and 8.3.3, vite --force, 40 cold starts 3 got no response all 40 answered
Vite 7.3.7, vite build --watch, two files importing each other exits early built in 253 ms
Vite 8.3.3, same still building after 20 s built in 53 ms
Rollup 4.64.0, rollup -c -w with @stylexjs/unplugin/rollup, same still building after 15 s built in 47 ms
Vite 7 and 8 build --watch without a cycle, then edit one file rebuilt CSS keeps the other files' rules same CSS as main
Rollup 4.59.0, second build in a new process given the first build's cache no StyleX CSS same CSS as the first build

@stylexjs/rollup-plugin has the same walk and the same rollup -w hang when two StyleX files import each other. I left it out to keep this PR to the unplugin, and can send the same change there separately.

The packages and prettier checks are failing on main right now because of the border radius test that #1907 fixes.

Pre-flight checklist

In watch mode, transform awaited this.load() on every import of a StyleX
file. That never finishes when two StyleX files import each other
(vite build --watch, rollup -w), and on a cold start of the Vite dev
server it can wait on the dependency optimizer, which is waiting on this
transform (meta#1912).

The walk also did nothing useful: it read meta.stylex, which transform
never returned. transform now returns meta: { stylex: rules }, so
shouldTransformCachedModule can restore the rules of a cached module.
That hook now also skips runtimeInjection builds and ignores meta
without a stylex array.
Copilot AI balanced review requested due to automatic review settings October 7, 2026 19:25
@vercel

vercel Bot commented Oct 7, 2026

Copy link
Copy Markdown

@Om-singhaI is attempting to deploy a commit to the Meta Open Source Team on Vercel.

A member of the Team first needs to authorize it.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 7, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Cached-module restoration does not synchronize shared and disk-backed rule stores, allowing stale or missing CSS.

1 open finding
What changed in this PR

Prevents watch-mode deadlocks by removing import loading from transforms and restoring cached StyleX rules through module metadata.

Changes:

  • Returns StyleX rules in transform metadata.
  • Restores cached rules without loading imports.
  • Adds watch-mode and cache-restoration regression tests.
File Description
src/​core.js Removes import walking and adds metadata-based restoration.
__tests__/​unplugin.test.js Covers deadlocks and cached-rule restoration.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +472 to +476
if (!stylexOptions.runtimeInjection && Array.isArray(meta?.stylex)) {
if (meta.stylex.length > 0) {
stylexRulesById.set(id, meta.stylex);
} else {
stylexRulesById.delete(id);

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[unplugin] Vite dev: import walk calls this.load() on dependencies (react), deadlocking the cold-start dependency optimizer

2 participants