mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 17:36:08 +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();
|
||||
const storage = require('../service/storage');
|
||||
await storage.loadStorageService();
|
||||
// Make sure everything is ready and then start main entry
|
||||
if (argv.options.watch) ctx.plugin(require('../service/watcher').default, {});
|
||||
ctx.plugin(require('../service/watcher').default, { watch: argv.options.watch });
|
||||
await require('../service/worker').apply(ctx);
|
||||
await require('../service/server').apply(ctx);
|
||||
await require('../service/api').apply(ctx);
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
/* eslint-disable import/no-dynamic-require */
|
||||
/* eslint-disable @typescript-eslint/no-shadow */
|
||||
import { readFileSync } from 'fs';
|
||||
import { relative, resolve, sep } from 'path';
|
||||
import { relative } from 'path';
|
||||
import { codeFrameColumns } from '@babel/code-frame';
|
||||
import { FSWatcher, watch } from 'chokidar';
|
||||
import { BuildFailure } from 'esbuild';
|
||||
import { Context, Plugin, Service } from '../context';
|
||||
import { Logger } from '../logger';
|
||||
@@ -15,6 +14,9 @@ declare module '../context' {
|
||||
interface Events {
|
||||
'hmr/reload': (reloads: Map<Plugin, { filename: string, runtime: Plugin.Runtime<Context> }>) => void;
|
||||
}
|
||||
interface Context {
|
||||
hmr: HMR;
|
||||
}
|
||||
}
|
||||
|
||||
function isBuildFailure(e: any): e is BuildFailure {
|
||||
@@ -59,57 +61,30 @@ function loadDependencies(filename: string, ignored: Set<string>) {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
const logger = new Logger('watch');
|
||||
const logger = new Logger('hmr');
|
||||
|
||||
export default class Watcher extends Service {
|
||||
private root: string;
|
||||
private watcher: FSWatcher;
|
||||
export default class HMR extends Service {
|
||||
private root = process.cwd();
|
||||
private externals: Set<string>;
|
||||
private accepted: Set<string>;
|
||||
private declined: Set<string>;
|
||||
private stashed = new Set<string>();
|
||||
|
||||
constructor(public ctx: Context) {
|
||||
super(ctx, 'watcher');
|
||||
constructor(public ctx: Context, config: { watch: boolean }) {
|
||||
super(ctx, 'hmr');
|
||||
this.externals = new Set(Object.keys(require.cache));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
const debouncedReload = ctx.debounce(() => this.triggerLocalReload(), 1000);
|
||||
this.ctx.on('app/watch/change', (path) => {
|
||||
if (this.externals.has(path)) {
|
||||
logger.warn('Require full reload');
|
||||
} else if (require.cache[path]) {
|
||||
this.stashed.add(path);
|
||||
this.ctx.emit('app/before-reload', this.stashed);
|
||||
triggerLocalReload();
|
||||
debouncedReload();
|
||||
this.ctx.emit('app/reload', this.stashed);
|
||||
}
|
||||
});
|
||||
this.watcher.on('unlink', (path) => {
|
||||
logger.debug('change detected:', `-${relative(this.root, path)}`);
|
||||
this.ctx.emit('app/watch/unlink', path);
|
||||
});
|
||||
}
|
||||
|
||||
stop() {
|
||||
return this.watcher.close();
|
||||
if (config.watch) ctx.plugin(require('./watch'));
|
||||
}
|
||||
|
||||
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