Skip to content

fix: file reloading mechanism and add profile watch ignores#2112

Open
ZerGo0 wants to merge 3 commits intowxt-dev:mainfrom
ZerGo0:fix/dev-watch-missed-reloads
Open

fix: file reloading mechanism and add profile watch ignores#2112
ZerGo0 wants to merge 3 commits intowxt-dev:mainfrom
ZerGo0:fix/dev-watch-missed-reloads

Conversation

@ZerGo0
Copy link
Contributor

@ZerGo0 ZerGo0 commented Feb 11, 2026

Overview

Fixes flaky dev reload detection where WXT sometimes ignores real source file saves.

Root cause:

  • Dev watcher used a debounced callback (leading: true, trailing: false) and queued events inside that callback.
  • With noisy filesystem activity (especially browser profile/cache files), relevant source change events could be dropped.

Changes:

  • Reworked dev file reload flow in packages/wxt/src/core/create-server.ts to:
    • queue every watcher event immediately
    • process the queue in a serialized loop
    • keep flushing after each debounce window until no new events arrive
  • Added runner profile watch ignores in packages/wxt/src/core/builders/vite/index.ts so browser profile churn is not watched:
    • chromiumProfile
    • firefoxProfile
    • chromiumArgs --user-data-dir (split and = forms)
    • firefoxArgs -profile (split and = forms)
  • Added a single regression test:
    • packages/wxt/src/core/__tests__/create-server.test.ts
    • Simulates browser-profile noise event followed by real source change and verifies the source change is detected/reloaded.

Manual Testing

This is pretty hard/annoying to reproduce. The new test is probably the best way of reproducing this: pnpm -C packages/wxt test --run src/core/__tests__/create-server.test.ts

  1. Use a project with browser profile inside project dir (example):
    • Chromium: chromiumArgs: ['--user-data-dir=./private/.dev-profile']
    • Firefox: firefoxProfile: './private/.dev-firefox-profile'
    • My main project does a ton of stuff in indexed dbs, this causes a ton of changes in the browser profile directory
  2. Run pnpm wxt.
  3. Save a real source file while browser is active.
  4. A rebuild should be triggered, but it just doesn't sometimes.

Related Issue

None I think.

@netlify
Copy link

netlify bot commented Feb 11, 2026

Deploy Preview for creative-fairy-df92c4 ready!

Name Link
🔨 Latest commit 9e4d40d
🔍 Latest deploy log https://app.netlify.com/projects/creative-fairy-df92c4/deploys/69903bc287eb4a00080c9707
😎 Deploy Preview https://deploy-preview-2112--creative-fairy-df92c4.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Member

@aklinker1 aklinker1 left a comment

Choose a reason for hiding this comment

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

Nice, I really like these changes!

I just woke up and am on mobile, so I'll need to do some manual testing to make sure everything is working later today.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 11, 2026

Open in StackBlitz

@wxt-dev/analytics

npm i https://pkg.pr.new/@wxt-dev/analytics@2112

@wxt-dev/auto-icons

npm i https://pkg.pr.new/@wxt-dev/auto-icons@2112

@wxt-dev/browser

npm i https://pkg.pr.new/@wxt-dev/browser@2112

@wxt-dev/i18n

npm i https://pkg.pr.new/@wxt-dev/i18n@2112

@wxt-dev/module-react

npm i https://pkg.pr.new/@wxt-dev/module-react@2112

@wxt-dev/module-solid

npm i https://pkg.pr.new/@wxt-dev/module-solid@2112

@wxt-dev/module-svelte

npm i https://pkg.pr.new/@wxt-dev/module-svelte@2112

@wxt-dev/module-vue

npm i https://pkg.pr.new/@wxt-dev/module-vue@2112

@wxt-dev/runner

npm i https://pkg.pr.new/@wxt-dev/runner@2112

@wxt-dev/storage

npm i https://pkg.pr.new/@wxt-dev/storage@2112

@wxt-dev/unocss

npm i https://pkg.pr.new/@wxt-dev/unocss@2112

@wxt-dev/webextension-polyfill

npm i https://pkg.pr.new/@wxt-dev/webextension-polyfill@2112

wxt

npm i https://pkg.pr.new/wxt@2112

commit: 9e4d40d

@codecov
Copy link

codecov bot commented Feb 11, 2026

Codecov Report

❌ Patch coverage is 52.50000% with 57 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.58%. Comparing base (cf31fbe) to head (9e4d40d).

Files with missing lines Patch % Lines
...ackages/wxt/src/core/utils/create-file-reloader.ts 49.39% 38 Missing and 4 partials ⚠️
packages/wxt/src/core/builders/vite/index.ts 37.50% 11 Missing and 4 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2112      +/-   ##
==========================================
+ Coverage   76.03%   76.58%   +0.54%     
==========================================
  Files         113      114       +1     
  Lines        3034     3079      +45     
  Branches      680      691      +11     
==========================================
+ Hits         2307     2358      +51     
+ Misses        643      638       -5     
+ Partials       84       83       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ZerGo0
Copy link
Contributor Author

ZerGo0 commented Feb 11, 2026

I pushed another small change. I don't really like the changes in 0cf79bb but I can't really think of a better way of doing this.

The problem is that it would show potentially wrong files in the "Changed: ..." log line and so on because they all use the "raw"/unfiltered queue. My latest commit fixes that.

@PatrykKuniczak
Copy link
Collaborator

I'm also have 1 file on which HMR doesn't work and i was about to report it, but i'll check it on your branch, maybe your PR will solve that issue 😄

Copy link
Member

@aklinker1 aklinker1 left a comment

Choose a reason for hiding this comment

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

Tested, things seem to behave the same way for me. One requested change.

* changes.
*/
function createFileReloader(server: WxtDevServer) {
export function createFileReloader(server: WxtDevServer) {
Copy link
Member

Choose a reason for hiding this comment

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

Exporting this here will export the function from the main wxt module as a public API, but I don't want this to be public. Move to another file, maybe in src/core/utils/create-file-reloader.ts, if you want to export and test it.

export * from './create-server';

export * from './core';

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, had to move a bit more than just createFileReloader.

- Exported `createFileReloader` function to allow external usage.
- Improved the file reloading process by implementing a queue worker to handle multiple file changes without dropping events.
- Added `getRunnerProfileWatchIgnores` function to dynamically generate ignored paths based on user profiles for Chromium and Firefox.
- Updated Vite builder configuration to include these new ignore patterns.
- Introduced `getRelevantDevChangedFiles` to filter out unrelated file changes.
- Updated `detectDevChanges` to utilize the new filtering function for improved accuracy.
- Modified `createFileReloader` to work with relevant file changes, ensuring only necessary reloads occur.
- Enhanced tests to validate the new behavior and ensure proper handling of HTML-only reloads.
Move createFileReloader into an internal core utils file and update create-server/test imports.
@PatrykKuniczak PatrykKuniczak force-pushed the fix/dev-watch-missed-reloads branch from 41b2084 to 9e4d40d Compare February 14, 2026 09:09
@PatrykKuniczak
Copy link
Collaborator

it's working for Windows also, but it doesn't solve my issue, i'll open new issue about it.

try {
const { output: newOutput } = await rebuild(
allEntrypoints,
// TODO: this excludes new entrypoints, so they're not built until the dev command is restarted
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's fix it or remove if it's outdated

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants