From d6b05493ae0017cb2f01dc1b702e95f2706f9677 Mon Sep 17 00:00:00 2001
From: ADNY <66500121+ErKeLost@users.noreply.github.com>
Date: Tue, 24 Dec 2024 10:49:52 +0800
Subject: [PATCH] refactor: v2 watcher (#2020)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
refactor: watcher
Co-authored-by: 苏向夜 <46275354+fu050409@users.noreply.github.com>
---
examples/vue3/src/App.vue | 3 +-
packages/core/src/server/index.ts | 10 +-
packages/core/src/watcher/index.ts | 151 +++++++++--------------------
3 files changed, 52 insertions(+), 112 deletions(-)
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);
}
};