UNPKG

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