diff --git a/examples/vue3/src/App.vue b/examples/vue3/src/App.vue index 77e69f349..5a4430f64 100644 --- a/examples/vue3/src/App.vue +++ b/examples/vue3/src/App.vue @@ -29,8 +29,7 @@ fetch("https://wallhaven.fun/api/wallhaven/w/yx6e9l").then((res) => res.json());
- - +
diff --git a/packages/core/src/server/index.ts b/packages/core/src/server/index.ts index 0ff729bcd..f66b340ba 100644 --- a/packages/core/src/server/index.ts +++ b/packages/core/src/server/index.ts @@ -244,11 +244,11 @@ export class Server extends httpServer { await this.watcher.createWatcher(); - this.watcher.watcher.on('add', async (file: string) => { + this.watcher.on('add', async (file: string) => { // TODO pluginContainer hooks }); - this.watcher.watcher.on('unlink', async (file: string) => { + this.watcher.on('unlink', async (file: string) => { const parentFiles = this.compiler.getParentFiles(file); const normalizeParentFiles = parentFiles.map((file) => normalizePath(file) @@ -256,7 +256,7 @@ export class Server extends httpServer { this.hmrEngine.hmrUpdate(normalizeParentFiles, true); }); - this.watcher.watcher.on('change', async (file: string) => { + this.watcher.on('change', async (file: string) => { file = normalizePath(file); const shortFile = getShortName(file, this.resolvedUserConfig.root); const isConfigFile = this.resolvedUserConfig.configFilePath === file; @@ -302,7 +302,7 @@ export class Server extends httpServer { ); if (filteredAdded.length > 0) { - this.watcher.watcher.add(filteredAdded); + this.watcher.add(filteredAdded); } }; @@ -699,7 +699,7 @@ export class Server extends httpServer { } await Promise.allSettled([ - this.watcher.watcher.close(), + this.watcher.close(), this.ws.wss.close(), this.closeHttpServerFn() ]); diff --git a/packages/core/src/watcher/index.ts b/packages/core/src/watcher/index.ts index 2a5f3b3a7..50ff62865 100644 --- a/packages/core/src/watcher/index.ts +++ b/packages/core/src/watcher/index.ts @@ -20,18 +20,53 @@ import type { export const debugWatcher = createDebugger('farm:watcher'); -export default class Watcher { - private watchedFiles = new Set(); +interface IWatcher { resolvedWatchOptions: WatchOptions; - watcher: FSWatcher; extraWatchedFiles: string[]; + getInternalWatcher(): FSWatcher; + filterWatchFile(file: string, root: string): boolean; + getExtraWatchedFiles(compiler?: Compiler | null): string[]; + watchExtraFiles(): void; + createWatcher(): Promise; + resolveChokidarOptions(): void; + close(): Promise; +} + +export default class Watcher extends EventEmitter implements IWatcher { + private watchedFiles = new Set(); + public resolvedWatchOptions: WatchOptions; + public extraWatchedFiles: string[] = []; + private _watcher: FSWatcher; constructor(public config: ResolvedUserConfig) { + super(); this.resolveChokidarOptions(); } + on( + event: 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir', + listener: (path: string) => void + ): this { + this._watcher.on(event, listener); + return this; + } + + add(paths: string | ReadonlyArray): this { + this._watcher.add(paths); + return this; + } + + unwatch(paths: string | ReadonlyArray): this { + this._watcher.unwatch(paths); + return this; + } + + getWatched(): { [directory: string]: string[] } { + return this._watcher.getWatched(); + } + getInternalWatcher() { - return this.watcher; + return this._watcher; } filterWatchFile(file: string, root: string): boolean { @@ -54,114 +89,20 @@ export default class Watcher { watchExtraFiles() { this.extraWatchedFiles.forEach((file) => { if (!this.watchedFiles.has(file)) { - this.watcher.add(file); + this._watcher.add(file); this.watchedFiles.add(file); } }); } - async watch() {} - - // async watch() { - // const compiler = this.getCompiler(); - - // const handlePathChange = async (path: string) => { - // if (this.close) return; - - // try { - // if (this.compiler instanceof NewServer && this.compiler.getCompiler()) { - // await this.compiler.hmrEngine.hmrUpdate(path); - // } - - // if ( - // this.compiler instanceof Compiler && - // this.compiler.hasModule(path) - // ) { - // await compilerHandler( - // async () => { - // const result = await compiler.update([path], true); - // this.handleUpdateFinish(result, compiler); - // compiler.writeResourcesToDisk(); - // }, - // this.config, - // this.logger, - // { clear: true } - // ); - // } - // } catch (error) { - // this.logger.error(error); - // } - // }; - - // const filesToWatch = [this.config.root, ...this.getExtraWatchedFiles()]; - // this.watchedFiles = new Set(filesToWatch); - // this.watcher ??= createWatcher(this.config, filesToWatch); - - // this.watcher.on('change', (path) => { - // if (this.close) return; - // handlePathChange(path); - // }); - - // if (this.compiler instanceof NewServer) { - // this.compiler.hmrEngine?.onUpdateFinish((result) => - // this.handleUpdateFinish(result, compiler) - // ); - // } - // } - - // async watchConfigs(callback: (files: string[]) => void) { - // const filesToWatch = Array.from([ - // ...(this.config.envFiles ?? []), - // ...(this.config.configFileDependencies ?? []), - // ...(this.config.configFilePath ? [this.config.configFilePath] : []) - // ]).filter((file) => file && existsSync(file)); - // const chokidarOptions = { - // awaitWriteFinish: - // process.platform === 'linux' - // ? undefined - // : { - // stabilityThreshold: 10, - // pollInterval: 80 - // } - // }; - // this.watcher ??= createWatcher(this.config, filesToWatch, chokidarOptions); - - // this.watcher.on('change', (path) => { - // if (this.close) return; - // if (filesToWatch.includes(path)) { - // callback([path]); - // } - // }); - // return this; - // } - - // private handleUpdateFinish(updateResult: JsUpdateResult, compiler: Compiler) { - // const addedFiles = [ - // ...updateResult.added, - // ...updateResult.extraWatchResult.add - // ].map((addedModule) => - // compiler.transformModulePath(this.config.root, addedModule) - // ); - - // const filteredAdded = addedFiles.filter((file) => - // this.filterWatchFile(file, this.config.root) - // ); - - // if (filteredAdded.length > 0) { - // this.watcher.add(filteredAdded); - // } - // } - async createWatcher() { const compiler = await createInlineCompiler(this.config, { progress: false }); - // TODO type error here - // @ts-ignore const enabledWatcher = this.config.watch !== null; const files = [this.config.root, ...this.getExtraWatchedFiles(compiler)]; - this.watcher = enabledWatcher + this._watcher = enabledWatcher ? (chokidar.watch(files, this.resolvedWatchOptions) as FSWatcher) : new NoopWatcher(this.resolvedWatchOptions); } @@ -200,10 +141,10 @@ export default class Watcher { } async close() { - if (this.watcher) { + if (this._watcher) { debugWatcher?.('close watcher'); - await this.watcher.close(); - this.watcher = null; + await this._watcher.close(); + this._watcher = null; } } } @@ -245,7 +186,7 @@ export async function handlerWatcher( const logger = resolvedUserConfig.logger; const watcher = new Watcher(resolvedUserConfig); await watcher.createWatcher(); - watcher.watcher.on('change', async (file: string | string[] | any) => { + watcher.on('change', async (file: string | string[] | any) => { file = normalizePath(file); // TODO restart with node side v2.0 we may be think about this feature // const shortFile = getShortName(file, resolvedUserConfig.root); @@ -278,7 +219,7 @@ export async function handlerWatcher( ); if (filteredAdded.length > 0) { - watcher.watcher.add(filteredAdded); + watcher.add(filteredAdded); } };