1 | #!/usr/bin/env node
|
2 | const { fork } = require('child_process');
|
3 | const parse = require('yargs-parser');
|
4 | const chokidar = require('chokidar');
|
5 | const detect = require('detect-port');
|
6 | const path = require('path');
|
7 | const log = require('../lib/utils/log');
|
8 |
|
9 | let child = null;
|
10 | const rawArgv = parse(process.argv.slice(2));
|
11 | const scriptPath = require.resolve('./child-process-start.js');
|
12 | const configPath = path.resolve(rawArgv.config || 'build.json');
|
13 |
|
14 | const inspectRegExp = /^--(inspect(?:-brk)?)(?:=(?:([^:]+):)?(\d+))?$/;
|
15 |
|
16 | async function modifyInspectArgv(execArgv, processArgv) {
|
17 | |
18 |
|
19 |
|
20 |
|
21 |
|
22 | const result = await Promise.all(
|
23 | execArgv.map(async item => {
|
24 | const matchResult = inspectRegExp.exec(item);
|
25 | if (!matchResult) {
|
26 | return item;
|
27 | }
|
28 | const [_, command, ip, port = 9229] = matchResult;
|
29 | const nPort = +port;
|
30 | const newPort = await detect(nPort);
|
31 | return `--${command}=${ip ? `${ip}:` : ''}${newPort}`
|
32 | })
|
33 | );
|
34 |
|
35 | |
36 |
|
37 |
|
38 |
|
39 | if (processArgv.inspect) {
|
40 | const matchResult = /(?:([^:]+):)?(\d+)/.exec(rawArgv.inspect);
|
41 | let [_, ip, port = 9229] = matchResult || [];
|
42 | const newPort = await detect(port);
|
43 | result.push(`--inspect=${ip ? `${ip}:` : ''}${newPort}`);
|
44 | }
|
45 |
|
46 | return result;
|
47 | }
|
48 |
|
49 | function restartProcess() {
|
50 | (async () => {
|
51 |
|
52 | const execArgv = await modifyInspectArgv(process.execArgv, rawArgv);
|
53 |
|
54 |
|
55 | const nProcessArgv = process.argv.slice(2).filter((arg) => arg.indexOf('--inspect') === -1);
|
56 | child = fork(scriptPath, nProcessArgv, { execArgv });
|
57 | child.on('message', data => {
|
58 | if (process.send) {
|
59 | process.send(data);
|
60 | }
|
61 | });
|
62 |
|
63 | child.on('exit', code => {
|
64 | if (code) {
|
65 | process.exit(code);
|
66 | }
|
67 | });
|
68 | })();
|
69 | }
|
70 |
|
71 | const onUserChange = () => {
|
72 | console.log('\n');
|
73 | log.info('build.json has been changed');
|
74 | log.info('restart dev server');
|
75 |
|
76 | process.env.RESTART_DEV = true;
|
77 | child.kill();
|
78 | restartProcess();
|
79 | };
|
80 |
|
81 | module.exports = () => {
|
82 | restartProcess();
|
83 |
|
84 | const watcher = chokidar.watch(configPath, {
|
85 | ignoreInitial: true,
|
86 | });
|
87 |
|
88 | watcher.on('change', onUserChange);
|
89 |
|
90 | watcher.on('error', error => {
|
91 | log.error('fail to watch file', error);
|
92 | process.exit(1);
|
93 | });
|
94 | };
|