forked from imbytecat/fullstack-starter
refactor: simplify compile.ts to single-target and add per-platform compile scripts
- Rewrite compile.ts from 112 to 66 lines: single target with auto-detect host, remove multi-target batch logic - Add compile:linux/mac/win scripts to server, root, and turbo configs - Wire desktop dist:* to depend on matching server compile:* (avoid unnecessary cross-platform compilation) - Update AGENTS.md docs across root, server, and desktop
This commit is contained in:
10
AGENTS.md
10
AGENTS.md
@@ -20,7 +20,10 @@ Guidelines for AI agents working in this Bun monorepo.
|
|||||||
```bash
|
```bash
|
||||||
bun dev # Start all apps in dev mode
|
bun dev # Start all apps in dev mode
|
||||||
bun build # Build all apps
|
bun build # Build all apps
|
||||||
bun compile # Compile server to standalone binary (depends on build)
|
bun compile # Compile server to standalone binary (current platform, depends on build)
|
||||||
|
bun compile:linux # Compile server for Linux x64
|
||||||
|
bun compile:mac # Compile server for macOS arm64
|
||||||
|
bun compile:win # Compile server for Windows x64
|
||||||
bun dist # Full packaging pipeline: server build → compile → desktop distributable (current platform)
|
bun dist # Full packaging pipeline: server build → compile → desktop distributable (current platform)
|
||||||
bun dist:linux # Full pipeline → Linux distributable
|
bun dist:linux # Full pipeline → Linux distributable
|
||||||
bun dist:mac # Full pipeline → macOS distributable
|
bun dist:mac # Full pipeline → macOS distributable
|
||||||
@@ -33,7 +36,10 @@ bun typecheck # TypeScript check across monorepo
|
|||||||
```bash
|
```bash
|
||||||
bun dev # Vite dev server (localhost:3000)
|
bun dev # Vite dev server (localhost:3000)
|
||||||
bun build # Production build -> .output/
|
bun build # Production build -> .output/
|
||||||
bun compile # Compile to standalone binary
|
bun compile # Compile to standalone binary (current platform)
|
||||||
|
bun compile:linux # Compile for Linux x64
|
||||||
|
bun compile:mac # Compile for macOS arm64
|
||||||
|
bun compile:win # Compile for Windows x64
|
||||||
bun fix # Biome auto-fix
|
bun fix # Biome auto-fix
|
||||||
bun typecheck # TypeScript check
|
bun typecheck # TypeScript check
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ bun typecheck # TypeScript check
|
|||||||
From monorepo root, run `bun dist` to execute the full pipeline automatically (via Turbo task dependencies):
|
From monorepo root, run `bun dist` to execute the full pipeline automatically (via Turbo task dependencies):
|
||||||
|
|
||||||
1. **Build server**: `apps/server` → `vite build` → `.output/`
|
1. **Build server**: `apps/server` → `vite build` → `.output/`
|
||||||
2. **Compile server**: `apps/server` → `bun compile.ts` → `out/server-{platform}`
|
2. **Compile server**: `apps/server` → `bun compile.ts` → `out/server-{os}-{arch}`
|
||||||
3. **Package desktop**: `apps/desktop` → `electron-vite build` + `electron-builder` → distributable
|
3. **Package desktop**: `apps/desktop` → `electron-vite build` + `electron-builder` → distributable
|
||||||
|
|
||||||
The `electron-builder.yml` `extraResources` config reads binaries directly from `../server/out/`, no manual copy needed.
|
The `electron-builder.yml` `extraResources` config reads binaries directly from `../server/out/`, no manual copy needed.
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
|
# yaml-language-server: $schema=https://raw.githubusercontent.com/electron-userland/electron-builder/refs/heads/master/packages/app-builder-lib/scheme.json
|
||||||
appId: com.furtherverse.app
|
appId: com.furtherverse.app
|
||||||
productName: Furtherverse
|
productName: Furtherverse
|
||||||
directories:
|
directories:
|
||||||
buildResources: build
|
buildResources: build
|
||||||
files:
|
files:
|
||||||
- '!**/.vscode/*'
|
- "!**/.vscode/*"
|
||||||
- '!src/*'
|
- "!src/*"
|
||||||
- '!electron.vite.config.{js,ts,mjs,cjs}'
|
- "!electron.vite.config.{js,ts,mjs,cjs}"
|
||||||
- '!{.env,.env.*,bun.lock}'
|
- "!{.env,.env.*,bun.lock}"
|
||||||
- '!{tsconfig.json,tsconfig.node.json}'
|
- "!{tsconfig.json,tsconfig.node.json}"
|
||||||
- '!{AGENTS.md,README.md,CHANGELOG.md}'
|
- "!{AGENTS.md,README.md,CHANGELOG.md}"
|
||||||
asarUnpack:
|
asarUnpack:
|
||||||
- resources/**
|
- resources/**
|
||||||
win:
|
win:
|
||||||
|
|||||||
@@ -25,8 +25,10 @@ bun db:studio # Drizzle Studio GUI
|
|||||||
|
|
||||||
# Build
|
# Build
|
||||||
bun build # Production build → .output/
|
bun build # Production build → .output/
|
||||||
bun compile # Compile to standalone binary (depends on build)
|
bun compile # Compile to standalone binary (current platform, depends on build)
|
||||||
# Also triggered automatically by root `bun dist`
|
bun compile:linux # Compile for Linux x64
|
||||||
|
bun compile:mac # Compile for macOS arm64
|
||||||
|
bun compile:win # Compile for Windows x64
|
||||||
|
|
||||||
# Code Quality
|
# Code Quality
|
||||||
bun fix # Biome auto-fix
|
bun fix # Biome auto-fix
|
||||||
|
|||||||
@@ -1,111 +1,66 @@
|
|||||||
import { rm } from 'node:fs/promises'
|
import { rm } from 'node:fs/promises'
|
||||||
import path from 'node:path'
|
|
||||||
import process from 'node:process'
|
import process from 'node:process'
|
||||||
|
|
||||||
const ALL_TARGETS = [
|
const ENTRYPOINT = '.output/server/index.mjs'
|
||||||
|
const OUTDIR = 'out'
|
||||||
|
|
||||||
|
const VALID_TARGETS = [
|
||||||
'bun-windows-x64',
|
'bun-windows-x64',
|
||||||
'bun-darwin-arm64',
|
'bun-darwin-arm64',
|
||||||
'bun-darwin-x64',
|
|
||||||
'bun-linux-x64',
|
'bun-linux-x64',
|
||||||
'bun-linux-arm64',
|
'bun-linux-arm64',
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
type BunTarget = (typeof ALL_TARGETS)[number]
|
type Target = (typeof VALID_TARGETS)[number]
|
||||||
|
|
||||||
const ENTRYPOINT = '.output/server/index.mjs'
|
const HOST_MAP: Record<string, Target> = {
|
||||||
const OUTDIR = 'out'
|
'win32-x64': 'bun-windows-x64',
|
||||||
const OUTFILE_BASE = 'server'
|
'darwin-arm64': 'bun-darwin-arm64',
|
||||||
|
'linux-x64': 'bun-linux-x64',
|
||||||
const DEFAULT_TARGETS: BunTarget[] = [
|
'linux-arm64': 'bun-linux-arm64',
|
||||||
'bun-windows-x64',
|
|
||||||
'bun-darwin-arm64',
|
|
||||||
'bun-linux-x64',
|
|
||||||
]
|
|
||||||
|
|
||||||
const suffixFor = (target: BunTarget) => target.replace('bun-', '')
|
|
||||||
|
|
||||||
const isTarget = (value: string): value is BunTarget =>
|
|
||||||
(ALL_TARGETS as readonly string[]).includes(value)
|
|
||||||
|
|
||||||
const parseTargets = (): BunTarget[] => {
|
|
||||||
const args = process.argv.slice(2)
|
|
||||||
const targets: string[] = []
|
|
||||||
|
|
||||||
for (let i = 0; i < args.length; i++) {
|
|
||||||
const arg = args[i]
|
|
||||||
const next = args[i + 1]
|
|
||||||
if (arg === '--target' && next) {
|
|
||||||
targets.push(next)
|
|
||||||
i++
|
|
||||||
} else if (arg === '--targets' && next) {
|
|
||||||
targets.push(...next.split(','))
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targets.length === 0) return DEFAULT_TARGETS
|
const resolveTarget = (): Target => {
|
||||||
|
const idx = process.argv.indexOf('--target')
|
||||||
const invalid = targets.filter((t) => !isTarget(t))
|
if (idx !== -1) {
|
||||||
if (invalid.length) {
|
const value = process.argv[idx + 1]
|
||||||
|
if (!value || !VALID_TARGETS.includes(value as Target)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unknown target(s): ${invalid.join(', ')}\nAllowed: ${ALL_TARGETS.join(', ')}`,
|
`Invalid target: ${value}\nAllowed: ${VALID_TARGETS.join(', ')}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return targets as BunTarget[]
|
return value as Target
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildOne = async (target: BunTarget) => {
|
const key = `${process.platform}-${process.arch}`
|
||||||
const suffix = suffixFor(target)
|
const target = HOST_MAP[key]
|
||||||
const outfile = `${OUTFILE_BASE}-${suffix}`
|
if (!target) {
|
||||||
|
throw new Error(`Unsupported host: ${key}`)
|
||||||
|
}
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
const target = resolveTarget()
|
||||||
|
const suffix = target.replace('bun-', '')
|
||||||
|
const outfile = `server-${suffix}`
|
||||||
|
|
||||||
|
await rm(OUTDIR, { recursive: true, force: true })
|
||||||
|
|
||||||
const result = await Bun.build({
|
const result = await Bun.build({
|
||||||
entrypoints: [ENTRYPOINT],
|
entrypoints: [ENTRYPOINT],
|
||||||
outdir: OUTDIR,
|
outdir: OUTDIR,
|
||||||
compile: {
|
compile: { outfile, target },
|
||||||
outfile,
|
|
||||||
target,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
throw new Error(
|
throw new Error(result.logs.map(String).join('\n'))
|
||||||
`Build failed for ${target}:\n${result.logs.map(String).join('\n')}`,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
console.log(`✓ ${target} → ${OUTDIR}/${outfile}`)
|
||||||
target,
|
|
||||||
outputs: result.outputs.map((o) => path.relative('.', o.path)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const main = async () => {
|
|
||||||
const targets = parseTargets()
|
|
||||||
|
|
||||||
await rm(OUTDIR, { recursive: true, force: true })
|
|
||||||
console.log(`✓ 已清理输出目录: ${OUTDIR}`)
|
|
||||||
|
|
||||||
// Bun cross-compile 不支持真正并行,逐目标串行构建
|
|
||||||
const results: Awaited<ReturnType<typeof buildOne>>[] = []
|
|
||||||
for (const target of targets) {
|
|
||||||
const start = Date.now()
|
|
||||||
process.stdout.write(`🔨 构建 ${target}... `)
|
|
||||||
const result = await buildOne(target)
|
|
||||||
results.push(result)
|
|
||||||
console.log(`完成 (${Date.now() - start}ms)`)
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('\n📦 构建完成:')
|
|
||||||
for (const r of results) {
|
|
||||||
console.log(` ${r.target}:`)
|
|
||||||
for (const p of r.outputs) {
|
|
||||||
console.log(` - ${p}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch((err) => {
|
main().catch((err) => {
|
||||||
console.error('\n❌ 构建失败:')
|
console.error('❌', err instanceof Error ? err.message : err)
|
||||||
console.error(err instanceof Error ? err.message : err)
|
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"compile": "bun compile.ts",
|
"compile": "bun compile.ts",
|
||||||
|
"compile:linux": "bun compile.ts --target bun-linux-x64",
|
||||||
|
"compile:mac": "bun compile.ts --target bun-darwin-arm64",
|
||||||
|
"compile:win": "bun compile.ts --target bun-windows-x64",
|
||||||
"db:generate": "drizzle-kit generate",
|
"db:generate": "drizzle-kit generate",
|
||||||
"db:migrate": "drizzle-kit migrate",
|
"db:migrate": "drizzle-kit migrate",
|
||||||
"db:push": "drizzle-kit push",
|
"db:push": "drizzle-kit push",
|
||||||
|
|||||||
@@ -8,6 +8,15 @@
|
|||||||
},
|
},
|
||||||
"compile": {
|
"compile": {
|
||||||
"outputs": ["out/**"]
|
"outputs": ["out/**"]
|
||||||
|
},
|
||||||
|
"compile:linux": {
|
||||||
|
"outputs": ["out/**"]
|
||||||
|
},
|
||||||
|
"compile:mac": {
|
||||||
|
"outputs": ["out/**"]
|
||||||
|
},
|
||||||
|
"compile:win": {
|
||||||
|
"outputs": ["out/**"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "turbo run build",
|
"build": "turbo run build",
|
||||||
"compile": "turbo run compile",
|
"compile": "turbo run compile",
|
||||||
|
"compile:linux": "turbo run compile:linux",
|
||||||
|
"compile:mac": "turbo run compile:mac",
|
||||||
|
"compile:win": "turbo run compile:win",
|
||||||
"dev": "turbo run dev",
|
"dev": "turbo run dev",
|
||||||
"dist": "turbo run dist",
|
"dist": "turbo run dist",
|
||||||
"dist:linux": "turbo run dist:linux",
|
"dist:linux": "turbo run dist:linux",
|
||||||
|
|||||||
15
turbo.json
15
turbo.json
@@ -9,6 +9,15 @@
|
|||||||
"compile": {
|
"compile": {
|
||||||
"dependsOn": ["build"]
|
"dependsOn": ["build"]
|
||||||
},
|
},
|
||||||
|
"compile:linux": {
|
||||||
|
"dependsOn": ["build"]
|
||||||
|
},
|
||||||
|
"compile:mac": {
|
||||||
|
"dependsOn": ["build"]
|
||||||
|
},
|
||||||
|
"compile:win": {
|
||||||
|
"dependsOn": ["build"]
|
||||||
|
},
|
||||||
"dist": {},
|
"dist": {},
|
||||||
"dist:linux": {},
|
"dist:linux": {},
|
||||||
"dist:mac": {},
|
"dist:mac": {},
|
||||||
@@ -17,13 +26,13 @@
|
|||||||
"dependsOn": ["@furtherverse/server#compile"]
|
"dependsOn": ["@furtherverse/server#compile"]
|
||||||
},
|
},
|
||||||
"@furtherverse/desktop#dist:linux": {
|
"@furtherverse/desktop#dist:linux": {
|
||||||
"dependsOn": ["@furtherverse/server#compile"]
|
"dependsOn": ["@furtherverse/server#compile:linux"]
|
||||||
},
|
},
|
||||||
"@furtherverse/desktop#dist:mac": {
|
"@furtherverse/desktop#dist:mac": {
|
||||||
"dependsOn": ["@furtherverse/server#compile"]
|
"dependsOn": ["@furtherverse/server#compile:mac"]
|
||||||
},
|
},
|
||||||
"@furtherverse/desktop#dist:win": {
|
"@furtherverse/desktop#dist:win": {
|
||||||
"dependsOn": ["@furtherverse/server#compile"]
|
"dependsOn": ["@furtherverse/server#compile:win"]
|
||||||
},
|
},
|
||||||
"dev": {
|
"dev": {
|
||||||
"cache": false,
|
"cache": false,
|
||||||
|
|||||||
Reference in New Issue
Block a user