startServer
1. 要做的事
在imooc-build start
命令中. 要做的事情
-
子进程启动 webpack-dev-serve服务. 以下是子进程启动原因
-
- 方便重启, 解决配置修改后, 无法重启的问题
-
- 避免主进程受影响, 万一子进程启动失败,报错了,不能影响主进程.可以让主进程再启动一个
- 启动子进程用 "child_process/fork"
-
-
监听配置修改, 如果配置变了, 要 杀死原服务, 再重新启动服务
- 文件监听用
chokidar.js
做 - 杀死原服务: child.kill();
- 重新启动服务: runServer()
- 文件监听用
const chokidar = require("chokidar");
const path = require("path");
const watcher = chokidar.watch(path.resolve(__dirname, ".config.json"));
watcher.on("change", (path) => {
console.log(path, "文件变更");
})
- 启动服务前, 判断端口号
-
- 设置一个默认端口
-
- 使用
detect-port
判断端口号是否重复, 如果重复返回可用端口号
- 使用
-
- 使用
inquirer
和用户交互, 让用户确认使用新端口
- 使用
-
2. 子进程相关
ps -ef // 查看进程信息
// 输出结果
UID PID PPID C STIME TTY TIME CMD
0 12321 0 0 08:00 ? 00:00:02 /sbin/init
109 22341 0 0 08:00 ? 00:00:00 ps
命令参数
- ps: process status. 进程状态. process进程, status 状态.
- ps -A: 显示所有进程信息, -A: all
- ps -l: 列表显示信息. -l: list
- ps -p 13360: 显示PID为13360的进程状态信息. -p: 指定pid
- ps -u 109: 显示UID为109的进程的状态信息. -u: 指定uid
命令结果
- UID: userId 用户id,例如109. ps -u 109.
- PID: process Id, 进程id, 例如22341. ps -p 22341
- PPID: parent process Id. 当前进程的父进程的id.
- C: cpu使用率
- STIME: start time. 开始时间
- TTY: Teletypewriter, 终端类型
- TIME: 进程消耗的 CPU 时间
- CMD: command. 启动进程的命令名称或路径.
3. 子进程的使用
node的子进程主要用于执行外部命令和脚本, 而不是直接执行函数, 如果非要执行函数, 可以把函数转成字符串执行.
用 child_process
处理子进程.
// node的子进程启动方式;
const cp = require("child_process");
// 单独起一个子进程来执行 js文件, "--force"是命令行参数, 等同于`node ./DevService.js --force`
cp.execFile("node", ["./DevService.js", "--force"], {}, (error, stdout) =>{
// stdout 是 DevService.js里的console的内容. DevService里的console并不会直接打印,而是传给stdout
console.log(error, stdout)
})
// exec里的内容是直接执行命令.
cp.exec("node ./Devservice.js --force", (error, stdout)=>{
console.log(error, stdout)
})
// 底层方法 child子进程对象
const child = cp.spawn("node", ["./Devservice.js", "--force"])
child.stdout.on("data", data => {
console.log(data.toString()); // data是子进程的console.log
})
child.stderr.on(data, err =>{
console.log(err.toString()); // err是子进程的报错
})
// close 当进程结束时(js文件执行完时),触发,
// code是进程编号,
child.on("close", code => {
// 根据进程编号结束进程.
process.exit(code)
})
4. 进程和子进程的通信
RPC: remote(远程) process(进程) communicate(通信)
fork方法专门用来创建有通信能力的进程;
是专门用来执行js文件用的.
const cp = require("child_process");
// 进程和子进程的相互通信
const child = cp.fork("./Devservice.js", ['--force'])
console.log("创建子进程");
child.on("message", data => {
console.log("父 message", data);
})
child.send({ name: "父 send" });
child.on("close", code => {
process.exit(code)
})
console.log("创建完毕")
// 子进程
process.on("message", msg => {
console.log("子 message", msg);
})
process.send({ name: "子 send" });
console.log("子进程结束");
最后输出 console
创建子进程 // 父进程开始
创建完毕 // 父进程结束
子进程结束 // 子进程结束
父 message { name: '子 send' } // 父进程的回调队列结束
子 message { name: '父 send' } // 子进程的回调队列结束
5. 命令行交互 - Inquirer
Inquirer是专门用来与用户交互的命令行工具, commander是专门用来解析命令行参数的工具;
type的类型
- "list", 展示选项, 让用户选择
- "password", 输入密码, 输入内容不可见
- "input", string 输入内容,
- "number", number 输入数字
- "confirm", boolean 输入Y/N
- "checkbox", 多选, 可不选.
(async ()=>{
const inquirer = require("inquirer");
const question = {
type: "list", // 列表方式
name: "val", // 返回值的key
message: "请选择", // 提示信息
choices: ["a", "b", "c"], // 具体选项
default: "a", // 默认值
};
const prompt = inquirer.createPromptModule();
const answer = await prompt(question);
console.log(answer); // {val: "a"}
})()
6. 同步执行promise函数
有些函数返回的是promise(比如detect
), 当我们不想用then获取返回值, 而是想同步执行,获取返回值时.
- 直接执行会返回promise,
const val = detect(port); //返回promise
- 加await结构promise,
const val = await detect(port);
, 会提示await需要在async中. - 加async, 会提示async不能在最外层.
- 给async加一层自执行函数. 完成.
(async ()=>{
const newPort = await detect(port);
// newPort就是promise解构后的返回值.
})()
7. detect-port 原理
- 解析传入的port, 设置最大值maxPort;
- 用net.Server创建一个TCP协议的请求.
- 用
server.listen(port, '')
测试port是否能正常启动 - 如果能正常启动,则用close关闭服务,并返回port.
- 再用server.listen测试地址为"0.0.0.0"的情况,如果还能正常启动则port可用.
- 如果启动失败,则port=port+1, 再试一次,直到maxPort.
const server = new net.Server();
// 请求地址为空的情况""
server.listen(port, "", () => {
port = server.address().port;
server.close();
// 请求地址为本地的情况
server.listen(port, "0.0.0.0", ()=>{
port = server.address().port;
server.close();
})
})
标签:const,process,startServer,console,child,进程,设计,脚手架,port
From: https://www.cnblogs.com/bridge7839/p/18573012