Skip to content

Commit 7fb7e54

Browse files
author
姚观寿
committed
实现了自动重启刷新node
1 parent f9ff009 commit 7fb7e54

File tree

14 files changed

+521
-222
lines changed

14 files changed

+521
-222
lines changed

.env

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
port=3002
12
htmlWebpackPluginOptions='{title:网页标题,webpackName:webpack-cli-util}'

bin/cmd.js

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* @Date: 2022-08-09 11:24:59
3+
* @Author: Yao guan shou
4+
* @LastEditors: Yao guan shou
5+
* @LastEditTime: 2022-08-09 13:22:27
6+
* @FilePath: /react-loading-ssr/bin/cmd.js
7+
* @Description:
8+
*/
9+
import os from 'os'
10+
import { spawn, SpawnOptions, exec, execSync } from 'child_process'
11+
import moment from 'moment'
12+
13+
14+
export default class Cmd {
15+
text = ''
16+
17+
runNodeModule(moduleName, params, options) {
18+
if (os.type() == 'Windows_NT' && !moduleName.match(/\.cmd$/)) {
19+
moduleName += '.cmd'
20+
}
21+
return this.run(moduleName, params, options)
22+
}
23+
24+
run(command, params, options) {
25+
this.text = ''
26+
// options = Object.assign(options || {}, { cwd: this.cfg.cwd });
27+
return new Promise((resolve, reject) => {
28+
console.log(`run command: ${command}, params:`, params, options)
29+
30+
if (!options) {
31+
options = {
32+
stdio: 'inherit',
33+
}
34+
}
35+
if (!params) params = []
36+
options.stdio = 'pipe'
37+
38+
let proc = spawn(command, params, options)
39+
// console.log('proc===', proc)
40+
41+
proc.stdout.on('data', (data) => {
42+
let dataStr = String(data)
43+
if (options.logPrefix) {
44+
dataStr = options.logPrefix + dataStr
45+
}
46+
this.text += dataStr
47+
if (!options?.silent)
48+
process.stdout.write(moment().format('HH:mm:ss:SSS ') + dataStr)
49+
})
50+
51+
proc.stderr.on('data', (data) => {
52+
// 不一定代表进程exitcode != 0,可能只是进程调用了console.error
53+
let dataStr = String(data)
54+
if (options?.logPrefix) {
55+
dataStr = options.logPrefix + dataStr
56+
}
57+
if (!options?.silent)
58+
process.stderr.write(moment().format('HH:mm:ss:SSS ') + dataStr)
59+
})
60+
61+
// 进程错误
62+
proc.on('error', (error) => {
63+
if (!options?.silent) console.error(error)
64+
reject(error)
65+
})
66+
67+
// 进程关闭
68+
proc.on('close', (code) => {
69+
console.log(`process closed with exit code: ${code}`)
70+
if (code == 0) {
71+
resolve(this.text || '')
72+
} else {
73+
let errMsg = `process closed with exit code: ${code}`
74+
if (options?.logPrefix) {
75+
errMsg = options.logPrefix + errMsg
76+
}
77+
reject(new Error(errMsg))
78+
}
79+
})
80+
81+
proc.on('exit', (code, signal) => {
82+
console.log(`process exits`)
83+
})
84+
})
85+
}
86+
}
87+
88+
// let cmd = new Cmd().runNodeModule(
89+
// process.platform === 'win32' ? 'npm.cmd' : 'npm',
90+
// ['run', 'ssr:dev', '--progress', 'bar:force'],
91+
// )
92+
93+
export const execute = (command, args = [], options = { stdio: 'inherit' }) => {
94+
const proc = spawn(command, args, options)
95+
96+
// 进程错误
97+
proc.on('error', (error) => {
98+
if (error) console.error(error)
99+
})
100+
101+
// 进程关闭
102+
proc.on('close', (code) => {
103+
console.log(`process closed with exit code: ${code}`)
104+
})
105+
106+
// 退出
107+
proc.on('exit', (code, signal) => {
108+
console.log(`process exits`)
109+
})
110+
111+
return proc
112+
}
113+
114+
/**
115+
* 判断端口是否被占用
116+
* @param port 端口号
117+
* @returns 该端口是否被占用
118+
*/
119+
export const iSportTake = (port) => {
120+
const cmd = process.platform === 'win32' ? 'netstat -aon|findstr' : 'lsof -i:'
121+
122+
let order = `${cmd}${port}`
123+
124+
try {
125+
const res = execSync(order)
126+
return true
127+
} catch (error) {
128+
console.log('error:', error)
129+
}
130+
return false
131+
}

bin/index.js

+69-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,69 @@
1-
//
2-
1+
/*
2+
* @Date: 2022-08-09 09:35:04
3+
* @Author: Yao guan shou
4+
* @LastEditors: Yao guan shou
5+
* @LastEditTime: 2022-08-09 13:52:05
6+
* @FilePath: /react-loading-ssr/bin/index.js
7+
* @Description:
8+
*/
9+
import cluster from 'cluster'
10+
import path from 'path'
11+
import os from 'os'
12+
import * as dotenv from 'dotenv'
13+
import { Worker } from 'worker_threads'
14+
import { copyFile, watchFile, readWriteFiles } from '../webpack/utils'
15+
import { spawn, SpawnOptions } from 'child_process'
16+
import kill from 'kill-port' // 杀死端口包
17+
import { execute, iSportTake } from './cmd' // 杀死端口包
18+
import { stabilization } from '../client/utils'
19+
// 注入环境变量
20+
dotenv.config({ path: '.env' })
21+
// 如果是开发环境 先拷贝 服务器文件到 dist
22+
let {
23+
NODE_ENV, // 环境参数
24+
WEB_ENV, // 环境参数
25+
target, // 环境参数
26+
htmlWebpackPluginOptions = '',
27+
port,
28+
} = process.env // 环境参数
29+
console.log('target=======', target)
30+
const isSsr = target === 'ssr'
31+
// 是否是生产环境
32+
const isEnvProduction = NODE_ENV === 'production'
33+
// 是否是测试开发环境
34+
const isEnvDevelopment = NODE_ENV === 'development'
35+
let counter = 0
36+
let child = null
37+
if (isEnvDevelopment && isSsr) {
38+
readWriteFiles({
39+
from: path.join(process.cwd(), '/server/**/*').replace(/\\/gi, '/'),
40+
to: path.join(process.cwd(), '/dist/server').replace(/\\/gi, '/'),
41+
transform(content, absoluteFrom) {
42+
// let reg = /.jsx|.js$/g;
43+
// if (reg.test(absoluteFrom)) {
44+
// return $ResolveAlias.alias(content.toString(), '');
45+
// }
46+
return content
47+
},
48+
callback() {
49+
counter += 1
50+
if (child) {
51+
// spawn 杀死正在执行的子进程
52+
var kill = spawn('kill', [child.pid])
53+
}
54+
stabilization(300, () => {
55+
if (counter === 1) {
56+
child = execute(process.platform === 'win32' ? 'npm.cmd' : 'npm', [
57+
'run',
58+
'ssr:dev',
59+
])
60+
} else {
61+
child = execute(process.platform === 'win32' ? 'npm.cmd' : 'npm', [
62+
'run',
63+
'bin',
64+
])
65+
}
66+
})
67+
},
68+
})
69+
}

client/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @Date: 2022-08-04 09:21:17
33
* @Author: Yao guan shou
44
* @LastEditors: Yao guan shou
5-
* @LastEditTime: 2022-08-05 10:03:52
5+
* @LastEditTime: 2022-08-09 12:05:38
66
* @FilePath: /react-loading-ssr/client/index.js
77
* @Description:
88
*/
@@ -13,7 +13,7 @@ import app from './App/index.js';
1313
import Loadable from '@/component/Loadable';
1414
import { getHistory } from '@/router/history';
1515
import createStore from '@/redux';
16-
16+
1717
const store = createStore(window);
1818

1919
let renderComponent = module.hot ? render : hydrate;

client/utils/throttlingStabilization.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const stabilization = (() => {
2323
let timer = null;
2424
return (time, callback) => {
2525
return new Promise((resolve, reject) => {
26-
window.clearTimeout(timer);
26+
clearTimeout(timer);
2727
timer = setTimeout(() => {
2828
if (callback && callback instanceof Function) {
2929
callback();

package.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"scripts": {
77
"web:dev": "cross-env target='web' COMPILER_ENV='middleware' npx babel-node -r dotenv/config ./server/index.js dotenv_config_path=.env.development",
88
"web:prod:build": "cross-env NODE_ENV=production COMPILER_ENV=webpack target=web htmlWebpackPluginOptions='{title:网页标题,webpackName:webpack-cli-util}' webpack -r @babel/register --progress --config ./webpack/config/client/index.js",
9-
109
"ssr:dev": "cross-env target='ssr' COMPILER_ENV='middleware' npx babel-node -r dotenv/config ./server/index.js dotenv_config_path=.env.development",
1110
"ssr:dev:build": "cross-env NODE_ENV=development COMPILER_ENV=webpack target=ssr htmlWebpackPluginOptions='{title:网页标题,webpackName:webpack-cli-util}' webpack -r @babel/register --progress --config ./webpack/config/client/index.js",
1211
"ssr:prod:build": "cross-env NODE_ENV=production COMPILER_ENV=webpack target=ssr htmlWebpackPluginOptions='{title:网页标题,webpackName:webpack-cli-util}' webpack -r @babel/register --progress --config ./webpack/config/client/index.js",
@@ -20,7 +19,9 @@
2019
"//注释10": "eslint校验",
2120
"eslint": "eslint ./src&&eslint ./server",
2221
"watchFile": "node ./webpack/utils/watchFile.js",
23-
"test": "node -r @babel/register ./client/assets/js/request/test.js"
22+
"test": "node -r @babel/register ./client/assets/js/request/test.js",
23+
"bin": "cross-env NODE_ENV=development target=ssr node -r @babel/register ./bin/index.js",
24+
"cmd": "cross-env NODE_ENV=development target=ssr node -r @babel/register ./bin/cmd.js"
2425
},
2526
"author": "",
2627
"license": "ISC",
@@ -99,6 +100,7 @@
99100
"happypack": "^5.0.1",
100101
"history": "5.3.0",
101102
"html-webpack-plugin": "4.4.1",
103+
"kill-port": "^2.0.1",
102104
"koa": "^2.4.1",
103105
"koa-router": "^12.0.0",
104106
"koa-static-cache": "^5.1.1",
@@ -107,6 +109,7 @@
107109
"less-loader": "^4.0.5",
108110
"map-stream": "^0.0.7",
109111
"mini-css-extract-plugin": "1.6.2",
112+
"moment": "^2.29.4",
110113
"node-fetch": "2",
111114
"nodemon": "^1.12.5",
112115
"npm-run-all": "^4.1.2",
@@ -138,4 +141,4 @@
138141
"webpack-merge": "4.1.0",
139142
"webpackbar": "^5.0.2"
140143
}
141-
}
144+
}

server/app.js

+48-43
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,57 @@
1-
require('./ignore.js')();
2-
import Loadable from 'react-loadable';
3-
import Koa from 'koa';
4-
import Router from './router';
5-
import Middleware from './middleware';
6-
7-
8-
// import { getEv } from '@/utils';
1+
/*
2+
* @Date: 2022-08-09 09:35:05
3+
* @Author: Yao guan shou
4+
* @LastEditors: Yao guan shou
5+
* @LastEditTime: 2022-08-09 13:51:20
6+
* @FilePath: /react-loading-ssr/server/app.js
7+
* @Description:
8+
*/
9+
// require('./ignore.js')()
10+
import Loadable from 'react-loadable'
11+
import Koa from 'koa'
12+
import Router from './router'
13+
import Middleware from './middleware'
914

1015
let {
11-
NODE_ENV, // 环境参数
12-
WEB_ENV, // 环境参数
13-
target, // 环境参数
14-
htmlWebpackPluginOptions = '',
15-
} = process.env; // 环境参数
16+
NODE_ENV, // 环境参数
17+
WEB_ENV, // 环境参数
18+
target, // 环境参数
19+
htmlWebpackPluginOptions = '',
20+
port,
21+
} = process.env // 环境参数
1622

23+
const b = 1133123
1724
// 是否是生产环境
18-
const isEnvProduction = NODE_ENV === 'production';
25+
const isEnvProduction = NODE_ENV === 'production'
1926
// 是否是测试开发环境
20-
const isEnvDevelopment = NODE_ENV === 'development';
21-
22-
const port = process.env.port || 3002;
27+
const isEnvDevelopment = NODE_ENV === 'development'
2328

2429
class App {
25-
constructor() {
26-
this.init();
27-
}
28-
init() {
29-
this.app = new Koa();
30-
this.addRouter();
31-
this.addMiddleware();
32-
this.listen();
33-
}
34-
addRouter() {
35-
new Router(this.app);
36-
}
37-
addMiddleware() {
38-
new Middleware(this.app);
39-
}
40-
listen() {
41-
Loadable.preloadAll().then(() => {
42-
const server = this.app.listen(port, function () {
43-
var port = server.address().port;
44-
console.log(
45-
`\n==> 🌎 node服务器启动成功,监听端口:${port}. 请打开浏览器 http://localhost:${port}/ \n`
46-
);
47-
});
48-
});
49-
}
30+
constructor() {
31+
this.init()
32+
}
33+
init() {
34+
this.app = new Koa()
35+
this.addRouter()
36+
this.addMiddleware()
37+
this.listen()
38+
}
39+
addRouter() {
40+
new Router(this.app)
41+
}
42+
addMiddleware() {
43+
new Middleware(this.app)
44+
}
45+
listen() {
46+
Loadable.preloadAll().then(() => {
47+
const server = this.app.listen(port, function () {
48+
var port = server.address().port
49+
console.log(
50+
`\n==> 🌎 node服务器启动成功,监听端口:${port}. 请打开浏览器 http://localhost:${port}/ \n`,
51+
)
52+
})
53+
})
54+
}
5055
}
5156

52-
export default App;
57+
export default App

0 commit comments

Comments
 (0)