mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-19 01:45:53 +00:00
perf: allow using @parcel/watcher
for dev watcher (#20179)
This commit is contained in:
parent
83f0103a47
commit
a086af9692
@ -99,6 +99,7 @@
|
||||
"vue-router": "^4.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@parcel/watcher": "^2.1.0",
|
||||
"@types/estree": "^1.0.1",
|
||||
"@types/fs-extra": "^11.0.1",
|
||||
"@types/prompts": "^2.4.4",
|
||||
@ -109,8 +110,14 @@
|
||||
"vitest": "^0.30.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@parcel/watcher": "^2.1.0",
|
||||
"@types/node": "^14.18.0 || ^16.10.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@parcel/watcher": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || ^16.10.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import type { EventType } from '@parcel/watcher'
|
||||
import chokidar from 'chokidar'
|
||||
import { isIgnored, tryResolveModule } from '@nuxt/kit'
|
||||
import { interopDefault } from 'mlly'
|
||||
import { debounce } from 'perfect-debounce'
|
||||
import { normalize } from 'pathe'
|
||||
import type { Nuxt } from 'nuxt/schema'
|
||||
@ -43,7 +45,45 @@ export async function build (nuxt: Nuxt) {
|
||||
}
|
||||
}
|
||||
|
||||
function watch (nuxt: Nuxt) {
|
||||
const watchEvents: Record<EventType, 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir'> = {
|
||||
create: 'add',
|
||||
delete: 'unlink',
|
||||
update: 'change'
|
||||
}
|
||||
|
||||
async function watch (nuxt: Nuxt) {
|
||||
if (nuxt.options.experimental.watcher === 'parcel') {
|
||||
if (nuxt.options.debug) {
|
||||
console.time('[nuxt] builder:parcel:watch')
|
||||
}
|
||||
const watcherPath = await tryResolveModule('@parcel/watcher', [nuxt.options.rootDir, ...nuxt.options.modulesDir])
|
||||
if (watcherPath) {
|
||||
const { subscribe } = await import(pathToFileURL(watcherPath).href).then(interopDefault) as typeof import('@parcel/watcher')
|
||||
for (const layer of nuxt.options._layers) {
|
||||
if (!layer.config.srcDir) { continue }
|
||||
const watcher = subscribe(layer.config.srcDir, (err, events) => {
|
||||
if (err) { return }
|
||||
for (const event of events) {
|
||||
if (isIgnored(event.path)) { continue }
|
||||
nuxt.callHook('builder:watch', watchEvents[event.type], normalize(event.path))
|
||||
}
|
||||
}, {
|
||||
ignore: [
|
||||
...nuxt.options.ignore,
|
||||
'.nuxt',
|
||||
'node_modules'
|
||||
]
|
||||
})
|
||||
watcher.then((subscription) => {
|
||||
console.timeEnd('[nuxt] builder:parcel:watch')
|
||||
nuxt.hook('close', () => subscription.unsubscribe())
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
console.warn('[nuxt] falling back to `chokidar` as `@parcel/watcher` cannot be resolved in your project.')
|
||||
}
|
||||
|
||||
if (nuxt.options.debug) {
|
||||
console.time('[nuxt] builder:chokidar:watch')
|
||||
}
|
||||
@ -65,7 +105,6 @@ function watch (nuxt: Nuxt) {
|
||||
|
||||
watcher.on('all', (event, path) => nuxt.callHook('builder:watch', event, normalize(path)))
|
||||
nuxt.hook('close', () => watcher.close())
|
||||
return watcher
|
||||
}
|
||||
|
||||
async function bundle (nuxt: Nuxt) {
|
||||
|
@ -1,10 +1,12 @@
|
||||
import { existsSync } from 'node:fs'
|
||||
import { mkdir, writeFile } from 'node:fs/promises'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { dirname, resolve } from 'pathe'
|
||||
import chokidar from 'chokidar'
|
||||
import { interopDefault } from 'mlly'
|
||||
import { defu } from 'defu'
|
||||
import { debounce } from 'perfect-debounce'
|
||||
import { createResolver, defineNuxtModule } from '@nuxt/kit'
|
||||
import { createResolver, defineNuxtModule, tryResolveModule } from '@nuxt/kit'
|
||||
import {
|
||||
generateTypes,
|
||||
resolveSchema as resolveUntypedSchema
|
||||
@ -57,6 +59,26 @@ export default defineNuxtModule({
|
||||
|
||||
// Watch for schema changes in development mode
|
||||
if (nuxt.options.dev) {
|
||||
const onChange = debounce(async () => {
|
||||
schema = await resolveSchema()
|
||||
await writeSchema(schema)
|
||||
})
|
||||
|
||||
if (nuxt.options.experimental.watcher === 'parcel') {
|
||||
const watcherPath = await tryResolveModule('@parcel/watcher', [nuxt.options.rootDir, ...nuxt.options.modulesDir])
|
||||
if (watcherPath) {
|
||||
const { subscribe } = await import(pathToFileURL(watcherPath).href).then(interopDefault) as typeof import('@parcel/watcher')
|
||||
for (const layer of nuxt.options._layers) {
|
||||
const subscription = await subscribe(layer.config.rootDir, onChange, {
|
||||
ignore: ['!nuxt.schema.*']
|
||||
})
|
||||
nuxt.hook('close', () => subscription.unsubscribe())
|
||||
}
|
||||
return
|
||||
}
|
||||
console.warn('[nuxt] 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.*')
|
||||
))
|
||||
@ -64,10 +86,6 @@ export default defineNuxtModule({
|
||||
...nuxt.options.watchers.chokidar,
|
||||
ignoreInitial: true
|
||||
})
|
||||
const onChange = debounce(async () => {
|
||||
schema = await resolveSchema()
|
||||
await writeSchema(schema)
|
||||
})
|
||||
watcher.on('all', onChange)
|
||||
nuxt.hook('close', () => watcher.close())
|
||||
}
|
||||
|
@ -345,6 +345,7 @@ export default defineUntypedSchema({
|
||||
'**/*.{spec,test}.{js,ts,jsx,tsx}', // ignore tests
|
||||
'**/*.d.ts', // ignore type declarations
|
||||
'.output',
|
||||
'.git',
|
||||
await get('ignorePrefix') && `**/${await get('ignorePrefix')}*.*`
|
||||
].concat(val).filter(Boolean)
|
||||
},
|
||||
|
@ -161,5 +161,19 @@ export default defineUntypedSchema({
|
||||
|
||||
/** Resolve `~`, `~~`, `@` and `@@` aliases located within layers with respect to their layer source and root directories. */
|
||||
localLayerAliases: true,
|
||||
|
||||
/**
|
||||
* 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
|
||||
* `@parcel/watcher` instead. This may improve performance in large projects or
|
||||
* on Windows platforms.
|
||||
*
|
||||
* @see https://github.com/paulmillr/chokidar
|
||||
* @see https://github.com/parcel-bundler/watcher
|
||||
* @default chokidar
|
||||
* @type {'chokidar' | 'parcel'}
|
||||
*/
|
||||
watcher: 'chokidar'
|
||||
}
|
||||
})
|
||||
|
@ -687,6 +687,9 @@ importers:
|
||||
specifier: ^4.1.6
|
||||
version: 4.1.6(vue@3.2.47)
|
||||
devDependencies:
|
||||
'@parcel/watcher':
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0
|
||||
'@types/estree':
|
||||
specifier: ^1.0.1
|
||||
version: 1.0.1
|
||||
@ -2133,6 +2136,17 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@parcel/watcher@2.1.0:
|
||||
resolution: {integrity: sha512-8s8yYjd19pDSsBpbkOHnT6Z2+UJSuLQx61pCFM0s5wSRvKCEMDjd/cHY3/GI1szHIWbpXpsJdg3V6ISGGx9xDw==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
is-glob: 4.0.3
|
||||
micromatch: 4.0.5
|
||||
node-addon-api: 3.2.1
|
||||
node-gyp-build: 4.6.0
|
||||
dev: true
|
||||
|
||||
/@pkgr/utils@2.3.1:
|
||||
resolution: {integrity: sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==}
|
||||
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
|
||||
@ -7238,6 +7252,10 @@ packages:
|
||||
resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==}
|
||||
dev: false
|
||||
|
||||
/node-addon-api@3.2.1:
|
||||
resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==}
|
||||
dev: true
|
||||
|
||||
/node-domexception@1.0.0:
|
||||
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
||||
engines: {node: '>=10.5.0'}
|
||||
|
Loading…
Reference in New Issue
Block a user