Avoid full reload in @tailwindcss/vite when editing a scanned file that is not a loaded module#20323
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
WalkthroughThe Vite plugin now detects external JavaScript and TypeScript files during hot updates and skips the full-reload path for them. A new integration test covers a scanned but unloaded module, captures HMR payloads, verifies an update instead of a full reload, and checks regenerated CSS. The changelog documents the fix under the unreleased changes. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
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 |
Confidence Score: 5/5This looks safe to merge.
Reviews (1): Last reviewed commit: "Add changelog entry" | Re-trigger Greptile |
Summary
Fixes #20320
In dev mode,
@tailwindcss/vite'shotUpdatehook has a fallback that sends afull-reloadfor files that Tailwind scans but that aren't handled by Vite or any plugin (e.g..phpor.htmltemplates). Without it, edits to those files wouldn't refresh the page at all.However, the check ("every module for this file is an
assetand/or has no id") also matches JS/TS source files that Tailwind has scanned but that Vite hasn't loaded as a module yet — lazy routes, unvisited chunks, and so on. The scanner'saddWatchFilecall creates an asset-type module-graph node withid === undefinedfor every scanned file, and for a not-yet-loaded.tsxthere is no real JS node next to it, so the fallback fires and the whole page reloads, throwing away all client state. In apps with route-level code splitting this happens on almost every edit to a not-currently-loaded component.This change exempts JS/TS module files (
.js,.jsx,.ts,.tsx,.mjs,.cjs,.mts,.cts) from the fallback. Vite handles these files itself whenever they are actually loaded, and for scanned-but-unloaded files any new candidates still flow through the regular CSS update, so nothing is lost by skipping the reload:.tsfile now results in a targeted{"type":"update"}for the Tailwind stylesheet instead of{"type":"full-reload"}, and the generated CSS includes the new candidates..phpfile still triggers a full reload as before.Test plan
src/unloaded.tsfile that is scanned but never imported. A small fixture plugin wrapsenvironment.hot.sendto log every HMR payload. The test editsunloaded.tsand asserts that anupdatepayload is sent (not afull-reload) and that the stylesheet regenerates with the new candidate.HOT_SEND {"type":"full-reload"}; after the change it logsHOT_SEND {"type":"update", ...}for/src/index.cssand the CSS contains the new candidate. Editing a scanned.phpfile still logsHOT_SEND {"type":"full-reload"}.