mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-22 21:55:11 +00:00
perf(nuxt): use granular watcher to avoid crawling ignored dirs (#20836)
This commit is contained in:
parent
ef8b5b593c
commit
9dea9bc1b2
@ -1,7 +1,8 @@
|
|||||||
import { pathToFileURL } from 'node:url'
|
import { pathToFileURL } from 'node:url'
|
||||||
import type { EventType } from '@parcel/watcher'
|
import type { EventType } from '@parcel/watcher'
|
||||||
|
import type { FSWatcher } from 'chokidar'
|
||||||
import chokidar from 'chokidar'
|
import chokidar from 'chokidar'
|
||||||
import { isIgnored, tryResolveModule } from '@nuxt/kit'
|
import { isIgnored, tryResolveModule, useNuxt } from '@nuxt/kit'
|
||||||
import { interopDefault } from 'mlly'
|
import { interopDefault } from 'mlly'
|
||||||
import { debounce } from 'perfect-debounce'
|
import { debounce } from 'perfect-debounce'
|
||||||
import { normalize } from 'pathe'
|
import { normalize } from 'pathe'
|
||||||
@ -55,6 +56,81 @@ const watchEvents: Record<EventType, 'add' | 'addDir' | 'change' | 'unlink' | 'u
|
|||||||
|
|
||||||
async function watch (nuxt: Nuxt) {
|
async function watch (nuxt: Nuxt) {
|
||||||
if (nuxt.options.experimental.watcher === 'parcel') {
|
if (nuxt.options.experimental.watcher === 'parcel') {
|
||||||
|
const success = await createParcelWatcher()
|
||||||
|
if (success) { return }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nuxt.options.experimental.watcher === 'chokidar') {
|
||||||
|
return createWatcher()
|
||||||
|
}
|
||||||
|
|
||||||
|
return createGranularWatcher()
|
||||||
|
}
|
||||||
|
|
||||||
|
function createWatcher () {
|
||||||
|
const nuxt = useNuxt()
|
||||||
|
|
||||||
|
const watcher = chokidar.watch(nuxt.options._layers.map(i => i.config.srcDir as string).filter(Boolean), {
|
||||||
|
...nuxt.options.watchers.chokidar,
|
||||||
|
cwd: nuxt.options.srcDir,
|
||||||
|
ignoreInitial: true,
|
||||||
|
ignored: [
|
||||||
|
isIgnored,
|
||||||
|
'.nuxt',
|
||||||
|
'node_modules'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
watcher.on('all', (event, path) => nuxt.callHook('builder:watch', event, normalize(path)))
|
||||||
|
nuxt.hook('close', () => watcher.close())
|
||||||
|
}
|
||||||
|
|
||||||
|
function createGranularWatcher () {
|
||||||
|
const nuxt = useNuxt()
|
||||||
|
|
||||||
|
if (nuxt.options.debug) {
|
||||||
|
console.time('[nuxt] builder:chokidar:watch')
|
||||||
|
}
|
||||||
|
|
||||||
|
let pending = 0
|
||||||
|
|
||||||
|
const ignoredDirs = new Set([...nuxt.options.modulesDir, nuxt.options.buildDir])
|
||||||
|
const pathsToWatch = nuxt.options._layers.map(layer => layer.config.srcDir).filter(d => d && !isIgnored(d))
|
||||||
|
for (const path of nuxt.options.watch) {
|
||||||
|
if (typeof path !== 'string') { continue }
|
||||||
|
if (pathsToWatch.some(w => path.startsWith(w.replace(/[^/]$/, '$&/')))) { continue }
|
||||||
|
pathsToWatch.push(path)
|
||||||
|
}
|
||||||
|
for (const dir of pathsToWatch) {
|
||||||
|
pending++
|
||||||
|
const watcher = chokidar.watch(dir, { ...nuxt.options.watchers.chokidar, ignoreInitial: false, depth: 0, ignored: [isIgnored] })
|
||||||
|
const watchers: Record<string, FSWatcher> = {}
|
||||||
|
|
||||||
|
watcher.on('all', (event, path) => {
|
||||||
|
if (!pending) {
|
||||||
|
nuxt.callHook('builder:watch', event, normalize(path))
|
||||||
|
}
|
||||||
|
if (event === 'unlinkDir' && path in watchers) {
|
||||||
|
watchers[path].close()
|
||||||
|
delete watchers[path]
|
||||||
|
}
|
||||||
|
if (event === 'addDir' && path !== dir && !ignoredDirs.has(path) && !(path in watchers) && !isIgnored(path)) {
|
||||||
|
watchers[path] = chokidar.watch(path, { ...nuxt.options.watchers.chokidar, ignored: [isIgnored] })
|
||||||
|
watchers[path].on('all', (event, path) => nuxt.callHook('builder:watch', event, normalize(path)))
|
||||||
|
nuxt.hook('close', () => watchers[path].close())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watcher.on('ready', () => {
|
||||||
|
pending--
|
||||||
|
if (nuxt.options.debug && !pending) {
|
||||||
|
console.timeEnd('[nuxt] builder:chokidar:watch')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createParcelWatcher () {
|
||||||
|
const nuxt = useNuxt()
|
||||||
if (nuxt.options.debug) {
|
if (nuxt.options.debug) {
|
||||||
console.time('[nuxt] builder:parcel:watch')
|
console.time('[nuxt] builder:parcel:watch')
|
||||||
}
|
}
|
||||||
@ -83,32 +159,10 @@ async function watch (nuxt: Nuxt) {
|
|||||||
nuxt.hook('close', () => subscription.unsubscribe())
|
nuxt.hook('close', () => subscription.unsubscribe())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return
|
return true
|
||||||
}
|
}
|
||||||
console.warn('[nuxt] falling back to `chokidar` as `@parcel/watcher` cannot be resolved in your project.')
|
console.warn('[nuxt] falling back to `chokidar-granular` as `@parcel/watcher` cannot be resolved in your project.')
|
||||||
}
|
return false
|
||||||
|
|
||||||
if (nuxt.options.debug) {
|
|
||||||
console.time('[nuxt] builder:chokidar:watch')
|
|
||||||
}
|
|
||||||
|
|
||||||
const watcher = chokidar.watch(nuxt.options._layers.map(i => i.config.srcDir as string).filter(Boolean), {
|
|
||||||
...nuxt.options.watchers.chokidar,
|
|
||||||
cwd: nuxt.options.srcDir,
|
|
||||||
ignoreInitial: true,
|
|
||||||
ignored: [
|
|
||||||
isIgnored,
|
|
||||||
'.nuxt',
|
|
||||||
'node_modules'
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
if (nuxt.options.debug) {
|
|
||||||
watcher.on('ready', () => console.timeEnd('[nuxt] builder:chokidar:watch'))
|
|
||||||
}
|
|
||||||
|
|
||||||
watcher.on('all', (event, path) => nuxt.callHook('builder:watch', event, normalize(path)))
|
|
||||||
nuxt.hook('close', () => watcher.close())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function bundle (nuxt: Nuxt) {
|
async function bundle (nuxt: Nuxt) {
|
||||||
|
@ -76,7 +76,7 @@ export default defineNuxtModule({
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
console.warn('[nuxt] falling back to `chokidar` as `@parcel/watcher` cannot be resolved in your project.')
|
console.warn('[nuxt] falling back to `chokidar-granular` as `@parcel/watcher` cannot be resolved in your project.')
|
||||||
}
|
}
|
||||||
|
|
||||||
const filesToWatch = await Promise.all(nuxt.options._layers.map(layer =>
|
const filesToWatch = await Promise.all(nuxt.options._layers.map(layer =>
|
||||||
|
@ -358,6 +358,7 @@ export default defineUntypedSchema({
|
|||||||
'.output',
|
'.output',
|
||||||
'.git',
|
'.git',
|
||||||
await get('analyzeDir'),
|
await get('analyzeDir'),
|
||||||
|
await get('buildDir'),
|
||||||
await get('ignorePrefix') && `**/${await get('ignorePrefix')}*.*`
|
await get('ignorePrefix') && `**/${await get('ignorePrefix')}*.*`
|
||||||
].concat(val).filter(Boolean)
|
].concat(val).filter(Boolean)
|
||||||
},
|
},
|
||||||
|
@ -161,15 +161,19 @@ export default defineUntypedSchema({
|
|||||||
/**
|
/**
|
||||||
* Set an alternative watcher that will be used as the watching service for Nuxt.
|
* Set an alternative watcher that will be used as the watching service for Nuxt.
|
||||||
*
|
*
|
||||||
* Nuxt uses 'chokidar' by default, but by setting this to `parcel` it will use
|
* Nuxt uses 'chokidar-granular' by default, which will ignore top-level directories
|
||||||
* `@parcel/watcher` instead. This may improve performance in large projects or
|
* (like `node_modules` and `.git`) that are excluded from watching.
|
||||||
* on Windows platforms.
|
*
|
||||||
|
* You can set this instead to `parcel` to use `@parcel/watcher`, which may improve
|
||||||
|
* performance in large projects or on Windows platforms.
|
||||||
|
*
|
||||||
|
* You can also set this to `chokidar` to watch all files in your source directory.
|
||||||
*
|
*
|
||||||
* @see https://github.com/paulmillr/chokidar
|
* @see https://github.com/paulmillr/chokidar
|
||||||
* @see https://github.com/parcel-bundler/watcher
|
* @see https://github.com/parcel-bundler/watcher
|
||||||
* @default chokidar
|
* @default chokidar
|
||||||
* @type {'chokidar' | 'parcel'}
|
* @type {'chokidar' | 'parcel' | 'chokidar-granular'}
|
||||||
*/
|
*/
|
||||||
watcher: 'chokidar'
|
watcher: 'chokidar-granular'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user