From afbb87d1f85fec29598592a1d3f7610c8ccc8fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Sat, 13 Aug 2022 16:19:46 +0900 Subject: [PATCH] docs: update WSL2 watch limitation explanation (#8939) Co-authored-by: Bjorn Lu --- docs/config/build-options.md | 7 +++++++ docs/config/server-options.md | 15 +++++++++++++-- packages/vite/src/node/build.ts | 19 +++++++------------ packages/vite/src/node/server/index.ts | 23 ++++++++++------------- packages/vite/src/node/watch.ts | 21 +++++++++++++++++++++ 5 files changed, 58 insertions(+), 27 deletions(-) create mode 100644 packages/vite/src/node/watch.ts diff --git a/docs/config/build-options.md b/docs/config/build-options.md index 586f84d6b24fd0..807b0f37640f4b 100644 --- a/docs/config/build-options.md +++ b/docs/config/build-options.md @@ -193,3 +193,10 @@ Limit for chunk size warnings (in kbs). - **Default:** `null` Set to `{}` to enable rollup watcher. This is mostly used in cases that involve build-only plugins or integrations processes. + +::: warning Using Vite on Windows Subsystem for Linux (WSL) 2 + +There are cases that file system watching does not work with WSL2. +See [`server.watch`](./server-options.md#server-watch) for more details. + +::: diff --git a/docs/config/server-options.md b/docs/config/server-options.md index 29a3582665c7a6..5092622e5d9f5e 100644 --- a/docs/config/server-options.md +++ b/docs/config/server-options.md @@ -169,8 +169,6 @@ The error that appears in the Browser when the fallback happens can be ignored. File system watcher options to pass on to [chokidar](https://github.com/paulmillr/chokidar#api). -When running Vite on Windows Subsystem for Linux (WSL) 2, if the project folder resides in a Windows filesystem, you'll need to set this option to `{ usePolling: true }`. This is due to [a WSL2 limitation](https://github.com/microsoft/WSL/issues/4739) with the Windows filesystem. - The Vite server watcher skips `.git/` and `node_modules/` directories by default. If you want to watch a package inside `node_modules/`, you can pass a negated glob pattern to `server.watch.ignored`. That is: ```js @@ -188,6 +186,19 @@ export default defineConfig({ }) ``` +::: warning Using Vite on Windows Subsystem for Linux (WSL) 2 + +When running Vite on WSL2, file system watching does not work when a file is edited by Windows applications (non-WSL2 process). This is due to [a WSL2 limitation](https://github.com/microsoft/WSL/issues/4739). This also applies to running on Docker with a WSL2 backend. + +To fix it, you could either: + +- **Recommended**: Use WSL2 applications to edit your files. + - It is also recommended to move the project folder outside of a Windows filesystem. Accessing Windows filesystem from WSL2 is slow. Removing that overhead will improve performance. +- Set `{ usePolling: true }`. + - Note that [`usePolling` leads to high CPU utilization](https://github.com/paulmillr/chokidar#performance). + +::: + ## server.middlewareMode - **Type:** `boolean` diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index fffeae697abc8b..174e5a33d9169a 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -49,6 +49,7 @@ import type { PackageData } from './packages' import { watchPackageDataPlugin } from './packages' import { ensureWatchPlugin } from './plugins/ensureWatch' import { ESBUILD_MODULES_TARGET, VERSION } from './constants' +import { resolveChokidarOptions } from './watch' export interface BuildOptions { /** @@ -504,23 +505,17 @@ async function doBuild( output.push(buildOutputOptions(outputs)) } - const watcherOptions = config.build.watch + const resolvedChokidarOptions = resolveChokidarOptions( + config.build.watch.chokidar + ) + const { watch } = await import('rollup') const watcher = watch({ ...rollupOptions, output, watch: { - ...watcherOptions, - chokidar: { - ignoreInitial: true, - ignorePermissionErrors: true, - ...watcherOptions.chokidar, - ignored: [ - '**/node_modules/**', - '**/.git/**', - ...(watcherOptions?.chokidar?.ignored || []) - ] - } + ...config.build.watch, + chokidar: resolvedChokidarOptions } }) diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts index 98d7814e587751..ee58ca6564753c 100644 --- a/packages/vite/src/node/server/index.ts +++ b/packages/vite/src/node/server/index.ts @@ -43,6 +43,7 @@ import { CLIENT_DIR } from '../constants' import type { Logger } from '../logger' import { printServerUrls } from '../logger' import { invalidatePackageData } from '../packages' +import { resolveChokidarOptions } from '../watch' import type { PluginContainer } from './pluginContainer' import { createPluginContainer } from './pluginContainer' import type { WebSocketServer } from './ws' @@ -300,6 +301,11 @@ export async function createServer( ) const { middlewareMode } = serverConfig + const resolvedWatchOptions = resolveChokidarOptions({ + disableGlobbing: true, + ...serverConfig.watch + }) + const middlewares = connect() as Connect.Server const httpServer = middlewareMode ? null @@ -310,19 +316,10 @@ export async function createServer( setClientErrorHandler(httpServer, config.logger) } - const { ignored = [], ...watchOptions } = serverConfig.watch || {} - const watcher = chokidar.watch(path.resolve(root), { - ignored: [ - '**/.git/**', - '**/node_modules/**', - '**/test-results/**', // Playwright - ...(Array.isArray(ignored) ? ignored : [ignored]) - ], - ignoreInitial: true, - ignorePermissionErrors: true, - disableGlobbing: true, - ...watchOptions - }) as FSWatcher + const watcher = chokidar.watch( + path.resolve(root), + resolvedWatchOptions + ) as FSWatcher const moduleGraph: ModuleGraph = new ModuleGraph((url, ssr) => container.resolveId(url, undefined, { ssr }) diff --git a/packages/vite/src/node/watch.ts b/packages/vite/src/node/watch.ts new file mode 100644 index 00000000000000..378610e28f3799 --- /dev/null +++ b/packages/vite/src/node/watch.ts @@ -0,0 +1,21 @@ +import type { WatchOptions } from 'types/chokidar' + +export function resolveChokidarOptions( + options: WatchOptions | undefined +): WatchOptions { + const { ignored = [], ...otherOptions } = options ?? {} + + const resolvedWatchOptions: WatchOptions = { + ignored: [ + '**/.git/**', + '**/node_modules/**', + '**/test-results/**', // Playwright + ...(Array.isArray(ignored) ? ignored : [ignored]) + ], + ignoreInitial: true, + ignorePermissionErrors: true, + ...otherOptions + } + + return resolvedWatchOptions +}