From 73a417499e74d4647542d5182e5de2bc0a40c174 Mon Sep 17 00:00:00 2001 From: "chenyongqing.cyq" Date: Tue, 4 May 2021 01:45:50 +0800 Subject: [PATCH] feat: sigint hooks (#33) --- packages/build-scripts/bin/start.js | 40 ++++++++++++++++++++ packages/build-scripts/src/commands/start.ts | 8 +++- packages/build-scripts/src/core/Context.ts | 31 +++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/packages/build-scripts/bin/start.js b/packages/build-scripts/bin/start.js index 9c5c81a..4c51880 100755 --- a/packages/build-scripts/bin/start.js +++ b/packages/build-scripts/bin/start.js @@ -5,6 +5,7 @@ const chokidar = require('chokidar'); const detect = require('detect-port'); const path = require('path'); const log = require('../lib/utils/log'); +const fse = require('fs-extra'); let child = null; const rawArgv = parse(process.argv.slice(2)); @@ -65,9 +66,48 @@ function restartProcess() { process.exit(code); } }); + + process.on('SIGINT', () => { + const rootDir = process.cwd(); + const SIGINThooksFileName = 'SIGINThooks.json'; + const hooksPath = path.resolve(rootDir, SIGINThooksFileName); + let hooks = legalSIGINThooks(hooksPath); + if (hooks) { + applySIGINThooks(hooks, hooksPath); + } + process.exit(1); + }) })(); } +const legalSIGINThooks = (hooksPath) => { + let hooks; + if (fse.existsSync(hooksPath)) { + hooks = fse.readJsonSync(hooksPath); + } + return hooks; +} + +const applySIGINThooks = (hooks, hooksPath) => { + + log.info('handleing SIGINThooks...'); + try { + hooks.forEach(item => { + try { + const fn = eval(item); + fn(); + } catch(e) { + log.error('SIGINThook item error', e); + } + }) + } catch (e) { + log.error('SIGINThooks error', e); + } + fse.removeSync(hooksPath); + log.info('handleing SIGINThooks finished'); + return +} + const onUserChange = () => { console.log('\n'); log.info('build.json has been changed'); diff --git a/packages/build-scripts/src/commands/start.ts b/packages/build-scripts/src/commands/start.ts index a7e53b6..8ad1072 100644 --- a/packages/build-scripts/src/commands/start.ts +++ b/packages/build-scripts/src/commands/start.ts @@ -33,7 +33,11 @@ export = async function({ log.verbose('OPTIONS', `${command} cliOptions: ${JSON.stringify(args, null, 2)}`); let serverUrl = ''; - const { applyHook, webpack } = context; + const { + applyHook, + webpack, + removeSIGINThooks, + } = context; let configArr = []; try { @@ -108,6 +112,8 @@ export = async function({ isFirstCompile, stats, }); + + removeSIGINThooks(); }); // require webpack-dev-server after context setup // context may hijack webpack resolve diff --git a/packages/build-scripts/src/core/Context.ts b/packages/build-scripts/src/core/Context.ts index b97a2e2..893c6f3 100644 --- a/packages/build-scripts/src/core/Context.ts +++ b/packages/build-scripts/src/core/Context.ts @@ -72,6 +72,10 @@ export interface IOnHook { (eventName: string, callback: IOnHookCallback): void; } +export interface IOnSIGINThooks { + (callback: (() => void)): void; +} + export interface IPluginConfigWebpack { (config: WebpackChain): void; } @@ -678,6 +682,33 @@ class Context { this.configArr = this.configArr.filter((config) => !this.cancelTaskNames.includes(config.name)); return this.configArr; } + + public removeSIGINThooks: () => void = () => { + const SIGINThooksFileName = 'SIGINThooks.json'; + const hooksPath = path.resolve(this.rootDir, SIGINThooksFileName); + if (fs.existsSync(hooksPath)) { + fs.removeSync(hooksPath); + } + } + + public onSIGINThooks: IOnSIGINThooks = (fn) => { + if (!fn || (typeof fn !== 'function')) { + log.warn('siginthooks arg wrong', 'fn should be function or stringify function'); + return; + } + + fn = (fn as any).toString(); + + const SIGINThooksFileName = 'SIGINThooks.json'; + const hooksPath = path.resolve(this.rootDir, SIGINThooksFileName); + if (!fs.existsSync(hooksPath)) { + fs.ensureFileSync(hooksPath); + fs.outputFileSync(hooksPath, JSON.stringify([])); + } + const hooks = fs.readJsonSync(hooksPath); + hooks.push(fn); + fs.outputFileSync(hooksPath, JSON.stringify(hooks)); + } } export default Context;