Skip to content

Commit

Permalink
fix: set watcher shared data only on change event
Browse files Browse the repository at this point in the history
  • Loading branch information
leegeunhyeok committed Oct 16, 2023
1 parent df3855f commit 7ff0675
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 17 deletions.
21 changes: 14 additions & 7 deletions packages/core/lib/bundler/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ export class ReactNativeEsbuildBundler extends BundlerEventEmitter {
this.on('report', (event) => {
this.broadcastToReporter(event);
});
this.setupWatcher();
}

private broadcastToReporter(event: ReportableEvent): void {
Expand Down Expand Up @@ -121,17 +120,23 @@ export class ReactNativeEsbuildBundler extends BundlerEventEmitter {
}

private setupWatcher(): void {
logger.debug('setup watcher');
FileSystemWatcher.getInstance()
.setHandler((changedFile, stats) => {
if (this.buildTasks.size > 0) {
.setHandler((event, changedFile, stats) => {
if (this.buildTasks.size > 0 && event === 'change') {
ReactNativeEsbuildBundler.shared.watcher = {
changed: changedFile,
stats,
};
} else {
ReactNativeEsbuildBundler.shared.watcher = {
changed: null,
stats: undefined,
};
}

for (const { context } of this.buildTasks.values()) {
context.rebuild();
for (const { context, handler } of this.buildTasks.values()) {
context.rebuild().catch((error) => handler?.rejecter?.(error));
}
})
.watch(this.root);
Expand Down Expand Up @@ -312,20 +317,22 @@ export class ReactNativeEsbuildBundler extends BundlerEventEmitter {

if (!this.buildTasks.has(targetTaskId)) {
logger.debug(`bundle task not registered (id: ${targetTaskId})`);
this.setupWatcher();
const buildOptions = await this.getBuildOptionsForBundler(
'watch',
bundleOptions,
additionalData,
);
const handler = createPromiseHandler();
const context = await esbuild.context(buildOptions);
this.buildTasks.set(targetTaskId, {
context,
handler: createPromiseHandler(),
handler,
status: 'pending',
buildCount: 0,
});
// trigger first build
context.rebuild();
context.rebuild().catch((error) => handler.rejecter?.(error));
logger.debug(`bundle task is now watching (id: ${targetTaskId})`);
}

Expand Down
42 changes: 32 additions & 10 deletions packages/core/lib/watcher/FileSystemWatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ const WATCH_EXTENSIONS_REGEXP = new RegExp(
);

export class FileSystemWatcher {
public static DEBOUNCE_DELAY = 300;
private static instance: FileSystemWatcher | null = null;
private watcher: chokidar.FSWatcher | null = null;
private onWatch?: (path: string, stats?: Stats) => void;
private onWatch?: (event: string, path: string, stats?: Stats) => void;
private debounceTimer?: NodeJS.Timeout;

private constructor() {
// empty constructor
Expand All @@ -28,15 +30,24 @@ export class FileSystemWatcher {
return FileSystemWatcher.instance;
}

private handleWatch(path: string, stats?: Stats): void {
private handleWatch(event: string, path: string, stats?: Stats): void {
logger.debug('event received from watcher', { path });
if (!WATCH_EXTENSIONS_REGEXP.test(path)) {
if (
this.debounceTimer !== undefined ||
!WATCH_EXTENSIONS_REGEXP.test(path)
) {
return;
}
this.onWatch?.(path, stats);

this.debounceTimer = setTimeout(() => {
this.debounceTimer = undefined;
this.onWatch?.(event, path, stats);
}, FileSystemWatcher.DEBOUNCE_DELAY);
}

setHandler(handler: (path: string, stats?: Stats) => void): this {
setHandler(
handler: (event: string, path: string, stats?: Stats) => void,
): this {
this.onWatch = handler;
return this;
}
Expand All @@ -49,23 +60,34 @@ export class FileSystemWatcher {

const ignoreDirectories = [path.join(targetPath, LOCAL_CACHE_DIR)];

const addListener = (
event: 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir',
): void => {
if (!this.watcher) return;
this.watcher.on(event, (path, stats) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- allow
this.handleWatch(event, path, stats);
});
};

this.watcher = chokidar
.watch(targetPath, {
alwaysStat: true,
ignoreInitial: true,
ignored: ignoreDirectories,
})
.on('add', this.handleWatch.bind(this) as typeof this.handleWatch)
.on('addDir', this.handleWatch.bind(this) as typeof this.handleWatch)
.on('change', this.handleWatch.bind(this) as typeof this.handleWatch)
.on('unlink', this.handleWatch.bind(this) as typeof this.handleWatch)
.on('unlinkDir', this.handleWatch.bind(this) as typeof this.handleWatch)
.on('ready', () => {
logger.debug(`watching '${targetPath}'`);
})
.on('error', (error) => {
logger.error('unexpected error on watcher', error);
});

addListener('addDir');
addListener('unlinkDir');
addListener('add');
addListener('change');
addListener('unlink');
}

close(): void {
Expand Down

2 comments on commit 7ff0675

@vercel
Copy link

@vercel vercel bot commented on 7ff0675 Oct 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report

St.
Category Percentage Covered / Total
🔴 Statements 15.64% 358/2289
🔴 Branches 18.37% 140/762
🔴 Functions 10.82% 71/656
🔴 Lines 14.87% 314/2112

Test suite run success

98 tests passing in 14 suites.

Report generated by 🧪jest coverage report action from 7ff0675

Please sign in to comment.