mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: split hmr and watcher
This commit is contained in:
3 files changed
+45
-40
No files matched your search
@@ -39,8 +39,7 @@ export async function apply(ctx: Context) {
|
|||||||
await modelSystem.runConfig();
|
await modelSystem.runConfig();
|
||||||
const storage = require('../service/storage');
|
const storage = require('../service/storage');
|
||||||
await storage.loadStorageService();
|
await storage.loadStorageService();
|
||||||
// Make sure everything is ready and then start main entry
|
ctx.plugin(require('../service/watcher').default, { watch: argv.options.watch });
|
||||||
if (argv.options.watch) ctx.plugin(require('../service/watcher').default, {});
|
|
||||||
await require('../service/worker').apply(ctx);
|
await require('../service/worker').apply(ctx);
|
||||||
await require('../service/server').apply(ctx);
|
await require('../service/server').apply(ctx);
|
||||||
await require('../service/api').apply(ctx);
|
await require('../service/api').apply(ctx);
|
||||||
|
|||||||
@@ -3,9 +3,8 @@
|
|||||||
/* eslint-disable import/no-dynamic-require */
|
/* eslint-disable import/no-dynamic-require */
|
||||||
/* eslint-disable @typescript-eslint/no-shadow */
|
/* eslint-disable @typescript-eslint/no-shadow */
|
||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
import { relative, resolve, sep } from 'path';
|
import { relative } from 'path';
|
||||||
import { codeFrameColumns } from '@babel/code-frame';
|
import { codeFrameColumns } from '@babel/code-frame';
|
||||||
import { FSWatcher, watch } from 'chokidar';
|
|
||||||
import { BuildFailure } from 'esbuild';
|
import { BuildFailure } from 'esbuild';
|
||||||
import { Context, Plugin, Service } from '../context';
|
import { Context, Plugin, Service } from '../context';
|
||||||
import { Logger } from '../logger';
|
import { Logger } from '../logger';
|
||||||
@@ -15,6 +14,9 @@ declare module '../context' {
|
|||||||
interface Events {
|
interface Events {
|
||||||
'hmr/reload': (reloads: Map<Plugin, { filename: string, runtime: Plugin.Runtime<Context> }>) => void;
|
'hmr/reload': (reloads: Map<Plugin, { filename: string, runtime: Plugin.Runtime<Context> }>) => void;
|
||||||
}
|
}
|
||||||
|
interface Context {
|
||||||
|
hmr: HMR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isBuildFailure(e: any): e is BuildFailure {
|
function isBuildFailure(e: any): e is BuildFailure {
|
||||||
@@ -59,57 +61,30 @@ function loadDependencies(filename: string, ignored: Set<string>) {
|
|||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
const logger = new Logger('watch');
|
const logger = new Logger('hmr');
|
||||||
|
|
||||||
export default class Watcher extends Service {
|
export default class HMR extends Service {
|
||||||
private root: string;
|
private root = process.cwd();
|
||||||
private watcher: FSWatcher;
|
|
||||||
private externals: Set<string>;
|
private externals: Set<string>;
|
||||||
private accepted: Set<string>;
|
private accepted: Set<string>;
|
||||||
private declined: Set<string>;
|
private declined: Set<string>;
|
||||||
private stashed = new Set<string>();
|
private stashed = new Set<string>();
|
||||||
|
|
||||||
constructor(public ctx: Context) {
|
constructor(public ctx: Context, config: { watch: boolean }) {
|
||||||
super(ctx, 'watcher');
|
super(ctx, 'hmr');
|
||||||
this.externals = new Set(Object.keys(require.cache));
|
this.externals = new Set(Object.keys(require.cache));
|
||||||
}
|
const debouncedReload = ctx.debounce(() => this.triggerLocalReload(), 1000);
|
||||||
|
this.ctx.on('app/watch/change', (path) => {
|
||||||
start() {
|
|
||||||
this.root = resolve(process.cwd());
|
|
||||||
const roots = [this.root];
|
|
||||||
if (process.env.WATCH_ROOT) roots.push(process.env.WATCH_ROOT);
|
|
||||||
this.watcher = watch(roots, {
|
|
||||||
ignored: (file) => [
|
|
||||||
'node_modules', '.git', 'logs', '.cache', '.yarn', 'tsconfig.tsbuildinfo',
|
|
||||||
].some((rule) => file.startsWith(`${rule}/`) || file.endsWith(`/${rule}`) || file.includes(`/${rule}/`)),
|
|
||||||
});
|
|
||||||
logger.info(`Start watching changes in ${this.root}`);
|
|
||||||
|
|
||||||
// files independent from any plugins will trigger a full reload
|
|
||||||
const triggerLocalReload = this.ctx.debounce(() => this.triggerLocalReload(), 1000);
|
|
||||||
|
|
||||||
this.watcher.on('change', (path) => {
|
|
||||||
if (path.includes(`${sep}.`)) return;
|
|
||||||
logger.debug('change detected:', relative(this.root, path));
|
|
||||||
this.ctx.emit('app/watch/change', path);
|
|
||||||
|
|
||||||
if (this.externals.has(path)) {
|
if (this.externals.has(path)) {
|
||||||
logger.warn('Require full reload');
|
logger.warn('Require full reload');
|
||||||
} else if (require.cache[path]) {
|
} else if (require.cache[path]) {
|
||||||
this.stashed.add(path);
|
this.stashed.add(path);
|
||||||
this.ctx.emit('app/before-reload', this.stashed);
|
this.ctx.emit('app/before-reload', this.stashed);
|
||||||
triggerLocalReload();
|
debouncedReload();
|
||||||
this.ctx.emit('app/reload', this.stashed);
|
this.ctx.emit('app/reload', this.stashed);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.watcher.on('unlink', (path) => {
|
if (config.watch) ctx.plugin(require('./watch'));
|
||||||
logger.debug('change detected:', `-${relative(this.root, path)}`);
|
|
||||||
this.ctx.emit('app/watch/unlink', path);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
stop() {
|
|
||||||
return this.watcher.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private analyzeChanges() {
|
private analyzeChanges() {
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { relative, resolve, sep } from 'path';
|
||||||
|
import { watch } from 'chokidar';
|
||||||
|
import { Context } from '../context';
|
||||||
|
import { Logger } from '../logger';
|
||||||
|
|
||||||
|
const logger = new Logger('watcher');
|
||||||
|
|
||||||
|
export const apply = (ctx: Context) => {
|
||||||
|
const root = resolve(process.cwd());
|
||||||
|
const roots = [root];
|
||||||
|
if (process.env.WATCH_ROOT) roots.push(process.env.WATCH_ROOT);
|
||||||
|
const watcher = watch(roots, {
|
||||||
|
ignored: (file) => [
|
||||||
|
'node_modules', '.git', 'logs', '.cache', '.yarn', 'tsconfig.tsbuildinfo',
|
||||||
|
].some((rule) => file.startsWith(`${rule}/`) || file.endsWith(`/${rule}`) || file.includes(`/${rule}/`)),
|
||||||
|
});
|
||||||
|
logger.info(`Start watching changes in ${root}`);
|
||||||
|
// files independent from any plugins will trigger a full reload
|
||||||
|
watcher.on('change', (path) => {
|
||||||
|
if (path.includes(`${sep}.`)) return;
|
||||||
|
logger.debug('change detected:', relative(root, path));
|
||||||
|
ctx.emit('app/watch/change', path);
|
||||||
|
});
|
||||||
|
watcher.on('unlink', (path) => {
|
||||||
|
logger.debug('change detected:', `-${relative(root, path)}`);
|
||||||
|
ctx.emit('app/watch/unlink', path);
|
||||||
|
});
|
||||||
|
return () => {
|
||||||
|
watcher.close();
|
||||||
|
};
|
||||||
|
};
|
||||||
Reference in new issue
Block a user