Skip to content

Do not force full page reloads when using @tailwindcss/vite - #20414

Merged
RobinMalfait merged 5 commits into
mainfrom
fix/issue-20411
Aug 13, 2026
Merged

Do not force full page reloads when using @tailwindcss/vite#20414
RobinMalfait merged 5 commits into
mainfrom
fix/issue-20411

Conversation

@RobinMalfait

Copy link
Copy Markdown
Member

This PR removes all of the custom HMR handling we had in the @tailwindcss/vite plugin.

When Vite 7.1 was introduced, Vite stopped performing a full page reload for unknown files and instead started performing normal hmr updates. This resulted in this issue: #19637

At the time, it felt like something we could easily re-add: if a file is not covered by Vite, we can perform a full-reload. This meant that a .php file would trigger a full page reload as expected.

The reason the .php file triggered Vite in the first place is because those files were scanned by us (@tailwindcss/vite) so it made sense.

However, this then resulted in a plethora of issues, and it feels a bit like a game of whac-a-mole.

Fixes: #19744
Fixes: #19903
Fixes: #20320
Fixes: #20378
Fixes: #20411

We kept updating the logic by safelisting certain extensions, checking different servers and/or environments, handling the fact that server in the callback could be absent in experimental.bundledDev mode, etc. etc.

Now, when investigating the last issue (#20411), I can trigger full reloads by changing .json, .yaml or .svg files. This makes sense since they aren't handled by default.

So thinking about this more, I think it's just not Tailwind's responsibility to tell Vite to reload the browser or not. Yes, we use the addWatchFile API, so files are being watched because of us. However, our only goal is to update the .css file (and HMR that).

This means that we can just drop all the custom HMR handling we have in @tailwindcss/vite.

This also means that #19637 would regress and won't trigger full page reloads. But this can be easily handled by a plugin responsible for this behavior:

Test plan

  1. All tests pass
  2. Manually tested and changing unknown files don't result in a full page reload

@RobinMalfait
RobinMalfait requested a review from a team as a code owner August 13, 2026 14:20
@greptile-apps

greptile-apps Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Reviews (2): Last reviewed commit: "update CHANGELOG" | Re-trigger Greptile

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e59c34bc-db61-45e0-8c0c-d284b3ae6acb

📥 Commits

Reviewing files that changed from the base of the PR and between a256c8b and 5a95e2d.

📒 Files selected for processing (1)
  • CHANGELOG.md

Walkthrough

The Vite plugin removes server tracking and external-file full-reload handling. Existing integration tests now verify CSS HMR updates, with exceptions for Vite 6 and 7.0.8. A new Preact test verifies initial styles, component HMR updates, candidate rescanning after package.json changes, and no full-page reloads.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: removing forced full-page reloads from the @tailwindcss/vite plugin.
Description check ✅ Passed The description explains the removal of custom HMR handling and connects it to the reported reload and HMR issues.
Linked Issues check ✅ Passed The changes remove custom full-reload behavior, preserve CSS HMR, and add coverage for Vite, Preact, external files, and bundledDev issues.
Out of Scope Changes check ✅ Passed The code and test changes directly support removing custom HMR handling and resolving the linked reload and bundledDev issues.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
integrations/vite/preact.test.ts (2)

32-46: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Confirm that the hmr.log path matches the test working directory.

The wiretap plugin writes to path.resolve('hmr.log'), which resolves against the dev server process cwd. The test reads hmr.log relative to the test root. Prefer server.config.root so the log path stays stable if the spawn cwd changes.

♻️ Proposed change to anchor the log path
               configureServer(server) {
-                let logFile = path.resolve('hmr.log')
+                let logFile = path.resolve(server.config.root, 'hmr.log')
                 fs.writeFileSync(logFile, '')

130-163: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Assert the update payload for the rescanned candidate.

This block asserts that the CSS contains the new candidate and that no full-reload payload was sent. Add an assertion that an "type":"update" payload was sent after the package.json write, so a silent full page refresh by other means cannot pass the test.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1c00d1b2-27ca-4874-8da6-68446158a979

📥 Commits

Reviewing files that changed from the base of the PR and between b9286a7 and a256c8b.

📒 Files selected for processing (4)
  • integrations/vite/index.test.ts
  • integrations/vite/preact.test.ts
  • packages/@tailwindcss-vite/src/index.test.ts
  • packages/@tailwindcss-vite/src/index.ts
💤 Files with no reviewable changes (1)
  • packages/@tailwindcss-vite/src/index.test.ts

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