UNPKG

7.17 kBJavaScriptView Raw
1#!/usr/bin/env node
2
3const fs = require('fs-extra')
4const path = require('path')
5const util = require('util')
6const exec = util.promisify(require('child_process').exec)
7
8const program = require('commander')
9const npmRunScript = require('npm-run-script')
10const chalk = require('chalk')
11// const opn = require('opn')
12
13const {
14 keyFileProjectConfigTemp,
15 filenameBuildFail,
16} = require('../defaults/before-build')
17const sleep = require('../utils/sleep')
18// const readBuildConfigFile = require('../utils/read-build-config-file')
19const spinner = require('../utils/spinner')
20const setEnvFromCommand = require('../utils/set-env-from-command')
21const validateConfig = require('../libs/validate-config')
22const __ = require('../utils/translate')
23// const getCwd = require('../utils/get-cwd')
24
25program
26 .version(require('../package').version, '-v, --version')
27 .usage('[options]')
28 .option('--no-build', 'Don\'t build')
29 // .option('--pm2', 'Start with pm2')
30 .option('--config <config-file-path>', 'Set config file')
31 .option('--type <project-type>', 'Set project type')
32 .option('--port <port>', 'Set server port')
33 .option('--koot-test', 'Koot test mode')
34 .parse(process.argv)
35
36/**
37 * 打包生产环境,并启动服务器(如果可用)
38 */
39const run = async () => {
40 // console.log('================')
41
42 const {
43 build,
44 config,
45 type,
46 port,
47 kootTest = false
48 } = program
49
50 if (!kootTest)
51 // 清空 log
52 process.stdout.write('\x1B[2J\x1B[0f')
53
54 setEnvFromCommand({
55 config, type, port
56 })
57
58 // 读取构建配置
59 const {
60 dist,
61 // server,
62 [keyFileProjectConfigTemp]: filenameProjectConfigTemp,
63 } = await validateConfig()
64
65 const afterBuild = async () => {
66 // 删除过程中创建的临时文件
67 if (filenameProjectConfigTemp) {
68 const fileProjectConfigTemp = path.resolve(dist, filenameProjectConfigTemp)
69 if (fs.existsSync(fileProjectConfigTemp))
70 await fs.remove(filenameProjectConfigTemp)
71 }
72 }
73
74 // 打包
75 if (build) {
76 const building = spinner(chalk.yellowBright('[koot/build] ') + __('build.building'))
77 const fileBuildFail = path.resolve(dist, filenameBuildFail)
78 const { stderr } = await exec(
79 `koot-build`, {
80 env: {
81 KOOT_COMMAND_START: JSON.stringify(true)
82 }
83 }
84 )
85 // await new Promise((resolve, reject) => {
86 // const child = npmRunScript(
87 // `koot-build`, {
88 // // stdio: 'ignore',
89 // env: {
90 // KOOT_COMMAND_START: JSON.stringify(true)
91 // }
92 // }
93 // )
94 // // child.stdin.pipe(process.stdin)
95 // // child.stdout.pipe(process.stdout)
96 // // child.stderr.pipe(process.stderr)
97 // // child.stderr.on('data', err => {
98 // // console.trace(err)
99 // // })
100 // child.once('error', (error) => {
101 // console.trace(error)
102 // process.exit(1)
103 // reject(error)
104 // })
105 // child.once('exit', (exitCode) => {
106 // // console.trace('exit in', exitCode)
107 // resolve(exitCode)
108 // // process.exit(exitCode)
109 // })
110 // console.log(child.stderr)
111 // })
112
113 // 打包过程中遭遇错误
114 if (
115 fs.existsSync(fileBuildFail) &&
116 stderr && stderr !== ' '
117 ) {
118 await afterBuild()
119
120 // 标记 spinner 为出错
121 building.fail()
122
123 // console.log(typeof stderr)
124
125 // 打出错误报告
126 console.log('')
127 console.trace(stderr)
128
129 // 终止流程
130 return
131 }
132 building.succeed()
133 await sleep(100)
134 }
135
136 // if (!server) {
137 // // console.log(chalk.redBright('× '))
138 // opn(path.resolve(dist, 'public/index.html'))
139 // return
140 // }
141
142 await afterBuild()
143
144 // 运行服务器
145 const pathServerJS = path.resolve(dist, 'server/index.js')
146 // if (pm2) {
147 // // PM2 方式
148 // console.log('--- pm2 ---')
149 // const pm2 = require('pm2')
150 // const packageInfo = await fs.readJson(path.resolve(getCwd(), 'package.json'))
151 // const name = `${packageInfo.name}-server`
152 // // const cmd = `pm2`
153 // // + ` pm2.json --only ${name}`
154 // pm2.start(pathServerJS, {
155 // name,
156 // "script": pathServerJS,
157 // "max_memory_restart": "300M",
158 // "instances": 1,
159 // "exec_mode": "cluster",
160 // "out_file": path.resolve(getCwd(), "logs/dev/server.log"),
161 // "error_file": path.resolve(getCwd(), "logs/dev/server-error.log")
162 // })
163 // } else {
164 // 正常方式
165 const cmd = `node ${pathServerJS.replace(/\\/g, '/')}`
166 // console.log('cmd', cmd)
167 const child = npmRunScript(cmd, {})
168 // console.log('child', child)
169 await new Promise((resolve, reject) => {
170 child.once('error', (error) => {
171 console.trace(error)
172 process.exit(1)
173 reject(error)
174 })
175 child.once('exit', (exitCode) => {
176 // console.trace('exit in', exitCode)
177 resolve(exitCode)
178 // process.exit(exitCode)
179 })
180 })
181 // }
182
183 /*
184 await new Promise((resolve, reject) => {
185 console.log({
186 'process.env': process.env
187 })
188 const cmd = `node ${pathServerJS.replace(/\\/g, '/')}`
189 const child = spawn(
190 'node',
191 [`${pathServerJS.replace(/\\/g, '/')}`]
192 )
193
194 // child.stdin.pipe(process.stdin)
195 child.stdout.pipe(process.stdout)
196 // child.stderr.pipe(process.stderr)
197 console.log(process.cwd())
198 console.log(cmd)
199
200 // const child = npmRunScript(cmd, {})
201 child.once('error', (error) => {
202 console.trace(error)
203 process.exit(1)
204 reject(error)
205 })
206 child.once('exit', (exitCode) => {
207 // console.trace('exit in', exitCode)
208 resolve(exitCode)
209 // process.exit(exitCode)
210 })
211 })
212 */
213 const exitHandler = (/*options, err*/) => {
214 child.kill('SIGINT')
215 process.exit(0)
216 }
217
218 // do something when app is closing
219 process.on('exit', exitHandler);
220 // catches ctrl+c event
221 process.on('SIGINT', exitHandler);
222 // catches "kill pid" (for example: nodemon restart)
223 process.on('SIGUSR1', exitHandler);
224 process.on('SIGUSR2', exitHandler);
225 // catches uncaught exceptions
226 process.on('uncaughtException', exitHandler);
227}
228
229run()