用 justfile 在 Windows Terminal 快速启动开发环境

一次本地联调需要同时运行前端、后端服务、本地依赖包的构建监听和 Redis。每次依次进入目录、启动命令,再把终端拖到合适的位置,重复起来有些麻烦。我把日常入口集中到工作区根目录的 justfile,用 just dev-local 一起启动。

我还希望四个进程始终出现在固定的位置。前端必须等后端开始监听,窗格却不该因为启动顺序而改变。把这两个要求分开之后,方案其实很直接:Windows Terminal 负责布局,每个窗格里的进程负责自己的启动条件。

固定四窗格与独立启动条件示意

每个进程保留独立入口

just 是一个命令运行工具。把工作目录和命令写进 justfile 后,便可以在工作区根目录调用,不必记住每个项目放在哪里。

联调中,后端服务和依赖包的构建监听是两个进程。服务启动并不意味着包的代码修改会自动生成新的构建产物。前端通过本地包关联引用它时,构建监听也要同时运行。

目录可以整理为:

workspace/
  justfile
  frontend/
  service/
  scripts/
    dev-local.ps1
    wait-frontend.ps1

justfile 保留独立启动命令,总入口交给 PowerShell:

set windows-shell := ["pwsh", "-NoLogo", "-NoProfile", "-Command"]

dev-service:
    cd service && bun run dev

watch-package:
    cd service && bun run build:watch

dev-frontend:
    cd frontend && bun run dev

dev-redis:
    redis-server

dev-local:
    pwsh -NoLogo -NoProfile -File scripts/dev-local.ps1

这里使用 PowerShell 7、Bun 和本机可执行的 redis-server。dev、build:watch 对应各项目 package.json 中的脚本;本地包关联在首次配置或切换依赖来源时完成,不放进每次启动流程里。

只调试一个进程时仍然可以单独调用 recipe。总入口的便利不应以失去独立调试的能力为代价。

用拆分方向和焦点确定四宫格

Windows Terminal 的 split-pane 会拆分当前有焦点的窗格。只连续执行三次拆分,可能得到一排窄窗格,而不是四宫格。布局取决于每次拆分前,焦点位于哪个区域。

我采用的顺序是:从原始窗格左右拆分,在右侧上下拆分,把焦点移回左侧,再把左侧上下拆分。

┌───────────┬───────────┐
│ Frontend  │ Service   │
├───────────┼───────────┤
│ Redis     │ Build     │
└───────────┴───────────┘

下面的 scripts/dev-local.ps1 使用当前窗格作为前端,其余三个窗格启动对应 recipe。运行入口是 Windows Terminal 中一个尚未拆分的标签页;布局命令执行期间保持该窗口为活动窗口。

$ErrorActionPreference = 'Stop'
$root = (Resolve-Path "$PSScriptRoot/..").Path

if (-not $env:WT_SESSION) {
    throw '请在 Windows Terminal 中运行 just dev-local'
}

wt -w 0 split-pane -V -d $root --title Service pwsh -NoLogo -NoExit -Command 'just dev-service'
Start-Sleep -Milliseconds 300

wt -w 0 split-pane -H -d $root --title Build pwsh -NoLogo -NoExit -Command 'just watch-package'
Start-Sleep -Milliseconds 300

wt -w 0 move-focus left
Start-Sleep -Milliseconds 300

wt -w 0 split-pane -H -d $root --title Redis pwsh -NoLogo -NoExit -Command 'just dev-redis'

Set-Location $root
& "$PSScriptRoot/wait-frontend.ps1"

-V 将区域左右拆开,-H 将区域上下拆开。拆分后焦点进入新窗格,但启动脚本仍然在原始窗格执行,因此最后调用前端等待脚本时,它仍会占据左上角。

-w 0 指向最近使用的 Windows Terminal 窗口。连续调用之间的短暂停顿给终端处理布局留出时间,它不负责判断服务是否已经可用。多窗口切换、已有复杂布局等情况需要另行处理。

我把每个终端动作分成一次调用,也避免了分号在不同程序之间的歧义。Windows Terminal 用分号分隔子命令,PowerShell 也用它分隔语句;如果分号提前被 PowerShell 解释,后面的 split-pane、move-focus 就会被当成独立程序执行。终端细节集中在脚本中,外部即使用 Nushell 调用 just,也不需要再拼一条很长的嵌套命令。

前端位置固定,实际启动可以等待

前端窗格先存在,不代表前端进程必须最先启动。它可以等待后端服务可连接,再执行自己的命令。

scripts/wait-frontend.ps1 中的端口应与后端配置一致:

$ErrorActionPreference = 'Stop'
$root = (Resolve-Path "$PSScriptRoot/..").Path
$servicePort = 3000
$deadline = [DateTime]::UtcNow.AddSeconds(120)
$ready = $false

while ([DateTime]::UtcNow -lt $deadline) {
    $client = [System.Net.Sockets.TcpClient]::new()
    try {
        $connect = $client.ConnectAsync('127.0.0.1', $servicePort)
        if ($connect.Wait(500) -and $client.Connected) {
            $ready = $true
            break
        }
    } catch {
        # 服务尚未监听时继续等待。
    } finally {
        $client.Dispose()
    }
    Start-Sleep -Milliseconds 400
}

if (-not $ready) {
    throw "等待后端端口 $servicePort 超时,请检查 Service 窗格"
}

Set-Location (Join-Path $root 'frontend')
bun run dev

端口连接成功只能说明服务开始监听。如果前端还依赖数据库连接或缓存初始化,应等待能反映这些状态的健康检查接口。超时后停止前端启动,并让错误留在对应窗格里,排查时就能直接去看后端输出。

这样组织以后,布局和进程依赖各有归属。调整前端的等待条件,不需要移动窗格;更换终端的拆分方式,也不需要改各进程的启动命令。日常使用仍然只有一个入口,需要排查时再回到独立命令。

评论

评论加载中…

输入关键词开始搜索。

选择Enter 打开Esc 关闭CtrlK 唤起