Skip to content

Commit

Permalink
feat: allow passing down "null" to disable server watcher (#14208)
Browse files Browse the repository at this point in the history
Co-authored-by: Bjorn Lu <bjornlu.dev@gmail.com>
  • Loading branch information
sheremet-va and bluwy committed Sep 19, 2023
1 parent 68638f7 commit af5a95e
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 11 deletions.
4 changes: 3 additions & 1 deletion docs/config/server-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ The error that appears in the Browser when the fallback happens can be ignored.

## server.watch

- **Type:** `object`
- **Type:** `object | null`

File system watcher options to pass on to [chokidar](https://github.com/paulmillr/chokidar#api).

Expand All @@ -197,6 +197,8 @@ export default defineConfig({
})
```

If set to `null`, no files will be watched. `server.watcher` will provide a compatible event emitter, but calling `add` or `unwatch` will have no effect.

::: 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.
Expand Down
3 changes: 2 additions & 1 deletion docs/guide/api-javascript.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ interface ViteDevServer {
*/
httpServer: http.Server | null
/**
* Chokidar watcher instance.
* Chokidar watcher instance. If `config.server.watch` is set to `null`,
* returns a noop event emitter.
* https://github.com/paulmillr/chokidar#api
*/
watcher: FSWatcher
Expand Down
24 changes: 24 additions & 0 deletions packages/vite/src/node/server/__tests__/watcher.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { describe, expect, it } from 'vitest'
import { createServer } from '../index'

const stubGetWatchedCode = /getWatched\(\) \{.+?return \{\};.+?\}/s

describe('watcher configuration', () => {
it('when watcher is disabled, return noop watcher', async () => {
const server = await createServer({
server: {
watch: null,
},
})
expect(server.watcher.getWatched.toString()).toMatch(stubGetWatchedCode)
})

it('when watcher is not disabled, return chokidar watcher', async () => {
const server = await createServer({
server: {
watch: {},
},
})
expect(server.watcher.getWatched.toString()).not.toMatch(stubGetWatchedCode)
})
})
20 changes: 12 additions & 8 deletions packages/vite/src/node/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import type { BindCLIShortcutsOptions } from '../shortcuts'
import { CLIENT_DIR, DEFAULT_DEV_PORT } from '../constants'
import type { Logger } from '../logger'
import { printServerUrls } from '../logger'
import { resolveChokidarOptions } from '../watch'
import { createNoopWatcher, resolveChokidarOptions } from '../watch'
import type { PluginContainer } from './pluginContainer'
import { createPluginContainer } from './pluginContainer'
import type { WebSocketServer } from './ws'
Expand Down Expand Up @@ -84,10 +84,10 @@ export interface ServerOptions extends CommonServerOptions {
*/
hmr?: HmrOptions | boolean
/**
* chokidar watch options
* chokidar watch options or null to disable FS watching
* https://github.com/paulmillr/chokidar#api
*/
watch?: WatchOptions
watch?: WatchOptions | null
/**
* Create Vite dev server to be used as a middleware in an existing server
* @default false
Expand Down Expand Up @@ -354,11 +354,15 @@ export async function _createServer(
setClientErrorHandler(httpServer, config.logger)
}

const watcher = chokidar.watch(
// config file dependencies and env file might be outside of root
[root, ...config.configFileDependencies, config.envDir],
resolvedWatchOptions,
) as FSWatcher
// eslint-disable-next-line eqeqeq
const watchEnabled = serverConfig.watch !== null
const watcher = watchEnabled
? (chokidar.watch(
// config file dependencies and env file might be outside of root
[root, ...config.configFileDependencies, config.envDir],
resolvedWatchOptions,
) as FSWatcher)
: createNoopWatcher(resolvedWatchOptions)

const moduleGraph: ModuleGraph = new ModuleGraph((url, ssr) =>
container.resolveId(url, undefined, { ssr }),
Expand Down
29 changes: 28 additions & 1 deletion packages/vite/src/node/watch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { EventEmitter } from 'node:events'
import glob from 'fast-glob'
import type { WatchOptions } from 'dep-types/chokidar'
import type { FSWatcher, WatchOptions } from 'dep-types/chokidar'
import type { ResolvedConfig } from '.'

export function resolveChokidarOptions(
Expand All @@ -23,3 +24,29 @@ export function resolveChokidarOptions(

return resolvedWatchOptions
}

class NoopWatcher extends EventEmitter implements FSWatcher {
constructor(public options: WatchOptions) {
super()
}

add() {
return this
}

unwatch() {
return this
}

getWatched() {
return {}
}

async close() {
// noop
}
}

export function createNoopWatcher(options: WatchOptions): FSWatcher {
return new NoopWatcher(options)
}

0 comments on commit af5a95e

Please sign in to comment.