.mts
后缀client/ --- 前端 Vite 项目
src/main.mts --- 前端 TS 代码文件
index.html --- Vite 入口
vite.config.mts --- Vite 配置
tsconfig.json --- 前端 TS 配置
package.json
server/ --- 后端 Node.js Koa 项目
src/main.mts --- 后端 TS 代码文件
tsconfig.json --- 后端 TS 配置
package.json
dev.mjs
package.json
.mts
文件后,自动编译为 .mjs
,然后自动重启后端,已知 ts-node
运行 .mts
文件有一堆报错tsc -w
和 nodemon
和 vite
每一个都会阻塞终端,但我希望能实现 npm run dev
一步到位启动前后端开发环境{
"build": "vite build",
"dev": "vite --host=0.0.0.0",
"preview": "vite preview"
}
{
"build": "tsc",
"build:watch": "tsc -w",
"dev": "nodemon dist/main.mjs"
}
{
"build:client": "npm run build --prefix client",
"build:server": "npm run build --prefix server",
"build": "npm run build:client && npm run build:server",
"dev:client": "npm run dev --prefix client",
"dev:server": "npm run dev --prefix server",
"build:watch:server": "npm run build:watch --prefix server",
"dev": "node dev.mjs"
}
本来想用 concurrently
并发执行 tsc -w
和 nodemon
和 vite
的,可是 nodemon
执行前必须要确保待执行的 .mjs
文件存在,可是 tsc -w
不一定来得及编译完成,所以我就在 concurrently
加一个一次性的 tsc
,可是 concurrently
会执行一次 nodemon
,tsc -w
又会触发一次 nodemon
,如果 Koa 在服务运行中时还打印内容的话,终端就会出现重复的一堆打印内容,实在不优雅。
import { spawn } from 'cross-spawn'
const tscWatchProcess = spawn('npm', ['run', 'build:watch:server'])
await new Promise((resolve, reject) => {
tscWatchProcess.stdout.on('data',
/** @param {Buffer} chunk */
chunk => {
if (chunk.toString().includes('Watching for file changes')) {
resolve()
}
}
)
tscWatchProcess.stdout.on('error', reject)
tscWatchProcess.stderr.on('error', reject)
tscWatchProcess.stderr.on('data', reject)
})
const viteProcess = spawn('npm', ['run', 'dev:client'])
const modemonProcess = spawn('npm', ['run', 'dev:server'])
/**
* @param {string} tag
* @param {Buffer} chunk
* @param {boolean} isError
*/
const handler = (tag, chunk) => {
chunk.toString().split('\n').forEach(line => {
if (line) console.log(`${line}`)
})
}
viteProcess.stdout.on('data', chunk => handler('client', chunk))
modemonProcess.stdout.on('data', chunk => handler('server', chunk))
viteProcess.stderr.on('data', chunk => handler('client', chunk))
modemonProcess.stderr.on('data', chunk => handler('server', chunk))
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.