Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Imports outside of the root break on file rename #16399

Closed
7 tasks done
astoilkov opened this issue Apr 11, 2024 · 7 comments · Fixed by #16476 · May be fixed by #16473
Closed
7 tasks done

Imports outside of the root break on file rename #16399

astoilkov opened this issue Apr 11, 2024 · 7 comments · Fixed by #16476 · May be fixed by #16473
Labels
feat: hmr p4-important Violate documented behavior or significantly improves performance (priority)

Comments

@astoilkov
Copy link

astoilkov commented Apr 11, 2024

Describe the bug

I rename files frequently. Some of our files are outside of the root. Vite breaks with [plugin:vite:import-analysis] Failed to resolve import "../packages/calc.js" from "counter.js". Does the file exist? after renaming a file that's outside of the root folder. I expect it to not throw an error and just reload the page or hot refresh it.

Reproduction

https://stackblitz.com/edit/vitejs-vite-ttd4av?file=app%2Fcounter.js

Steps to reproduce

  • Go to the reproduction & run the project
  • Rename packages/calc.js to calc2.js
  • Fix the import in app/counter.js
  • The following error should appear:
    CleanShot 2024-04-11 at 11 51 49@2x

The only way I found to fix it is to restart Vite.

System Info

System:
    OS: macOS 14.3.1
    CPU: (8) arm64 Apple M1
    Memory: 96.75 MB / 8.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.18.2 - /usr/local/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 8.12.1 - /opt/homebrew/bin/npm
    pnpm: 7.15.0 - ~/Library/pnpm/pnpm
  Browsers:
    Chrome: 123.0.6312.107
    Safari: 17.3.1

Used Package Manager

yarn

Logs

No response

Validations

Copy link

stackblitz bot commented Apr 11, 2024

Fix this issue in StackBlitz Codeflow Start a new pull request in StackBlitz Codeflow.

@ChuTingzj
Copy link

It feel like counter-intuitive

@sapphi-red sapphi-red added feat: hmr p4-important Violate documented behavior or significantly improves performance (priority) labels Apr 12, 2024
@HawtinZeng
Copy link

HawtinZeng commented Apr 17, 2024

Hi, let's discuss this bug, when we load some files whose location is outside of the root, we will call watcher.add to include these files, watch the changes of these files.But When we rename these files, we will trigger 'old file delete event' and 'new file create event', because we haven't include the new file in watcher, we can't catch the 'new file create event', and can't trigger HMR.Related code as below:

export function ensureWatchedFile(
  watcher: FSWatcher,
  file: string | null,
  root: string,
): void {
  if (
    file &&
    // only need to watch if out of root
    !file.startsWith(withTrailingSlash(root)) &&
    // some rollup plugins use null bytes for private resolved Ids
    !file.includes('\0') &&
    fs.existsSync(file)
  ) {
    // resolve file to normalized system path
    watcher.add(path.resolve(file))
  }
}

Solution: Add the top directory of the outside file path to chokidar.

@XiSenao
Copy link
Collaborator

XiSenao commented Apr 17, 2024

It seems to be related to caching, and using the following configuration options can temporarily solve this problem.

export default defineConfig({
    server: {
        fs: {
            cachedChecks: false,
        }
    }
});

The external file-level listener seems to only trigger the unlink event when performing a rename operation, and does not trigger the add event. This may be due to cache invalidation.

Solution: Add the top directory of the outside file path to chokidar.

@HawtinZeng It seems that there is a high cost associated with modifying the monitored path to be the nearest common parent path of the external path and root path. I think that when handling external module paths (ensureWatchedFile), synchronously updating the cache seems to restore everything to normal 🤔.

@HawtinZeng
Copy link

HawtinZeng commented Apr 17, 2024

It seems to be related to caching, and using the following configuration options can temporarily solve this problem.

export default defineConfig({
    server: {
        fs: {
            cachedChecks: false,
        }
    }
});

The external file-level listener seems to only trigger the unlink event when performing a rename operation, and does not trigger the add event. This may be due to cache invalidation.

Solution: Add the top directory of the outside file path to chokidar.

@HawtinZeng It seems that there is a high cost associated with modifying the monitored path to be the nearest common parent path of the external path and root path. I think that when handling external module paths (ensureWatchedFile), synchronously updating the cache seems to restore everything to normal 🤔.

Hi, I have tried your method, it didn't work.Maybe a better solution is offer an option array to define where store external files, then we can watch these paths.

Or we can add the new file path into watcher while resolved new file path, It's much better.

@sapphi-red
Copy link
Member

It seems this is caused by #15712. I guess it's happening because of inconsistent values here.


const root = normalizePath(searchForWorkspaceRoot(config.root))

@dennis-meitner
Copy link

dennis-meitner commented Apr 19, 2024

I hope this is related otherwise I'll create a new issue. Vite now breaks when I'm trying to create a new file and import it anywhere. Same for moving files. And it's the same issue with "Failed to resolve import". The last version where this worked correctly is 5.0.13. Anything above(and including) 5.1.7 breaks in this particular way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat: hmr p4-important Violate documented behavior or significantly improves performance (priority)
Projects
None yet
6 participants