fix(kit,nuxt,schema,vite): improve watching behaviour (#30620)

This commit is contained in:
Daniel Roe 2025-01-16 15:02:01 +00:00 committed by GitHub
parent f1264e2812
commit bc669cba0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 39 additions and 24 deletions

View File

@ -3,12 +3,14 @@ import ignore from 'ignore'
import { join, relative, resolve } from 'pathe'
import { tryUseNuxt } from './context'
export function createIsIgnored (nuxt = tryUseNuxt()) {
return (pathname: string, stats?: unknown) => isIgnored(pathname, stats, nuxt)
}
/**
* Return a filter function to filter an array of paths
*/
export function isIgnored (pathname: string): boolean {
const nuxt = tryUseNuxt()
export function isIgnored (pathname: string, _stats?: unknown, nuxt = tryUseNuxt()): boolean {
// Happens with CLI reloads
if (!nuxt) {
return false

View File

@ -19,7 +19,7 @@ export { assertNuxtCompatibility, checkNuxtCompatibility, getNuxtVersion, hasNux
export { addComponent, addComponentsDir } from './components'
export type { AddComponentOptions } from './components'
export { nuxtCtx, tryUseNuxt, useNuxt } from './context'
export { isIgnored, resolveIgnorePatterns } from './ignore'
export { createIsIgnored, isIgnored, resolveIgnorePatterns } from './ignore'
export { addLayout } from './layout'
export { addRouteMiddleware, extendPages, extendRouteRules } from './pages'
export type { AddRouteMiddlewareOptions, ExtendRouteRulesOptions } from './pages'

View File

@ -58,7 +58,7 @@ export function TransformPlugin (nuxt: Nuxt, options: TransformPluginOptions) {
enforce: 'post',
transformInclude (id) {
id = normalize(id)
return id.startsWith('virtual:') || id.startsWith('\0virtual:') || id.startsWith(nuxt.options.buildDir) || !isIgnored(id)
return id.startsWith('virtual:') || id.startsWith('\0virtual:') || id.startsWith(nuxt.options.buildDir) || !isIgnored(id, undefined, nuxt)
},
async transform (code, id) {
// Virtual component wrapper

View File

@ -1,7 +1,7 @@
import type { EventType } from '@parcel/watcher'
import type { FSWatcher } from 'chokidar'
import { watch as chokidarWatch } from 'chokidar'
import { importModule, isIgnored, tryResolveModule, useNuxt } from '@nuxt/kit'
import { createIsIgnored, importModule, isIgnored, tryResolveModule, useNuxt } from '@nuxt/kit'
import { debounce } from 'perfect-debounce'
import { normalize, relative, resolve } from 'pathe'
import type { Nuxt, NuxtBuilder } from 'nuxt/schema'
@ -100,14 +100,12 @@ async function watch (nuxt: Nuxt) {
function createWatcher () {
const nuxt = useNuxt()
const isIgnored = createIsIgnored(nuxt)
const watcher = chokidarWatch(nuxt.options._layers.map(i => i.config.srcDir as string).filter(Boolean), {
...nuxt.options.watchers.chokidar,
ignoreInitial: true,
ignored: [
isIgnored,
'node_modules',
],
ignored: [isIgnored, /[\\/]node_modules[\\/]/],
})
watcher.on('all', (event, path) => {
@ -121,6 +119,7 @@ function createWatcher () {
function createGranularWatcher () {
const nuxt = useNuxt()
const isIgnored = createIsIgnored(nuxt)
if (nuxt.options.debug) {
// eslint-disable-next-line no-console
@ -139,7 +138,7 @@ function createGranularWatcher () {
}
for (const dir of pathsToWatch) {
pending++
const watcher = chokidarWatch(dir, { ...nuxt.options.watchers.chokidar, ignoreInitial: false, depth: 0, ignored: [isIgnored, '**/node_modules'] })
const watcher = chokidarWatch(dir, { ...nuxt.options.watchers.chokidar, ignoreInitial: false, depth: 0, ignored: [isIgnored, /[\\/]node_modules[\\/]/] })
const watchers: Record<string, FSWatcher> = {}
watcher.on('all', (event, path) => {

View File

@ -2,7 +2,7 @@ import { mkdir, open, readFile, stat, unlink, writeFile } from 'node:fs/promises
import type { FileHandle } from 'node:fs/promises'
import { resolve } from 'node:path'
import { existsSync } from 'node:fs'
import { isIgnored } from '@nuxt/kit'
import { createIsIgnored } from '@nuxt/kit'
import type { Nuxt, NuxtConfig, NuxtConfigLayer } from '@nuxt/schema'
import { hash, murmurHash, objectHash } from 'ohash'
import { glob } from 'tinyglobby'
@ -119,6 +119,7 @@ async function getHashes (nuxt: Nuxt, options: GetHashOptions): Promise<Hashes>
data: murmurHash(f.data as any /* ArrayBuffer */),
}))
const isIgnored = createIsIgnored(nuxt)
const sourceFiles = await readFilesRecursive(options.cwd(layer), {
shouldIgnore: isIgnored, // TODO: Validate if works with absolute paths
cwd: nuxt.options.rootDir,

View File

@ -5,11 +5,8 @@ import { resolve } from 'pathe'
import { watch } from 'chokidar'
import { defu } from 'defu'
import { debounce } from 'perfect-debounce'
import { createResolver, defineNuxtModule, importModule, tryResolveModule } from '@nuxt/kit'
import {
generateTypes,
resolveSchema as resolveUntypedSchema,
} from 'untyped'
import { createIsIgnored, createResolver, defineNuxtModule, importModule, tryResolveModule } from '@nuxt/kit'
import { generateTypes, resolveSchema as resolveUntypedSchema } from 'untyped'
import type { Schema, SchemaDefinition } from 'untyped'
import untypedPlugin from 'untyped/babel-plugin'
import { createJiti } from 'jiti'
@ -71,11 +68,17 @@ export default defineNuxtModule({
logger.warn('Falling back to `chokidar` as `@parcel/watcher` cannot be resolved in your project.')
}
const filesToWatch = await Promise.all(nuxt.options._layers.map(layer =>
resolver.resolve(layer.config.rootDir, 'nuxt.schema.*'),
))
const watcher = watch(filesToWatch, {
const isIgnored = createIsIgnored(nuxt)
const dirsToWatch = nuxt.options._layers.map(layer => resolver.resolve(layer.config.rootDir))
const SCHEMA_RE = /(?:^|\/)nuxt.schema.\w+$/
const watcher = watch(dirsToWatch, {
...nuxt.options.watchers.chokidar,
depth: 1,
ignored: [
(path, stats) => (stats && !stats.isFile()) || !SCHEMA_RE.test(path),
isIgnored,
/[\\/]node_modules[\\/]/,
],
ignoreInitial: true,
})
watcher.on('all', onChange)

View File

@ -1,5 +1,5 @@
import { existsSync } from 'node:fs'
import { addBuildPlugin, addTemplate, addTypeTemplate, defineNuxtModule, isIgnored, resolveAlias, tryResolveModule, updateTemplates, useNuxt } from '@nuxt/kit'
import { addBuildPlugin, addTemplate, addTypeTemplate, createIsIgnored, defineNuxtModule, resolveAlias, tryResolveModule, updateTemplates, useNuxt } from '@nuxt/kit'
import { isAbsolute, join, normalize, relative, resolve } from 'pathe'
import type { Import, Unimport } from 'unimport'
import { createUnimport, scanDirExports, toExports } from 'unimport'
@ -118,6 +118,7 @@ export default defineNuxtModule<Partial<ImportsOptions>>({
return IMPORTS_TEMPLATE_RE.test(template.filename)
}
const isIgnored = createIsIgnored(nuxt)
const regenerateImports = async () => {
await ctx.modifyDynamicImports(async (imports) => {
// Clear old imports

View File

@ -28,6 +28,7 @@ export default defineBuildConfig({
// Type imports
'@unhead/schema',
'@vitejs/plugin-vue',
'chokidar',
'@vitejs/plugin-vue-jsx',
'@vue/language-core',
'autoprefixer',

View File

@ -44,6 +44,7 @@
"@vue/compiler-sfc": "3.5.13",
"@vue/language-core": "2.2.0",
"c12": "2.0.1",
"chokidar": "4.0.3",
"compatx": "0.1.8",
"esbuild-loader": "4.2.2",
"file-loader": "6.2.0",

View File

@ -519,9 +519,11 @@ export default defineUntypedSchema({
/**
* Options to pass directly to `chokidar`.
* @see [chokidar](https://github.com/paulmillr/chokidar#api)
* @type {typeof import('chokidar').ChokidarOptions}
*/
chokidar: {
ignoreInitial: true,
ignorePermissionErrors: true,
},
},

View File

@ -2,7 +2,7 @@ import { existsSync } from 'node:fs'
import * as vite from 'vite'
import { dirname, join, normalize, resolve } from 'pathe'
import type { Nuxt, NuxtBuilder, ViteConfig } from '@nuxt/schema'
import { addVitePlugin, isIgnored, logger, resolvePath, useNitro } from '@nuxt/kit'
import { addVitePlugin, createIsIgnored, logger, resolvePath, useNitro } from '@nuxt/kit'
import replace from '@rollup/plugin-replace'
import type { RollupReplaceOptions } from '@rollup/plugin-replace'
import { sanitizeFilePath } from 'mlly'
@ -53,6 +53,7 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
const { $client, $server, ...viteConfig } = nuxt.options.vite
const isIgnored = createIsIgnored(nuxt)
const ctx: ViteBuildContext = {
nuxt,
entry,
@ -88,6 +89,7 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
},
},
watch: {
chokidar: { ...nuxt.options.watchers.chokidar, ignored: [isIgnored, /[\\/]node_modules[\\/]/] },
exclude: nuxt.options.ignore,
},
},
@ -101,7 +103,7 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
replace({ preventAssignment: true, ...globalThisReplacements }),
],
server: {
watch: { ignored: isIgnored },
watch: { ...nuxt.options.watchers.chokidar, ignored: [isIgnored, /[\\/]node_modules[\\/]/] },
fs: {
allow: [...new Set(allowDirs)],
},

View File

@ -690,6 +690,9 @@ importers:
c12:
specifier: 2.0.1
version: 2.0.1(magicast@0.3.5)
chokidar:
specifier: 4.0.3
version: 4.0.3
compatx:
specifier: 0.1.8
version: 0.1.8