Skip to content

Commit 3c1c4fe

Browse files
authored
🤖 perf: Use tsgo for main process compilation (19.6x faster) (#264)
## Summary Replaces `tsc` with `tsgo` for main process compilation, achieving a **19.6x speedup** (3.489s → 0.178s). Completes investigation of tsgo integration opportunities across the entire build toolchain. ## Performance Impact **Main process build:** - Before: 3.489s with tsc - After: 0.178s with tsgo - **Speedup: 19.6x** **Type checking (already optimized in PR #260):** - Before: 5.942s with tsc - After: 0.776s with tsgo - **Speedup: 7.7x** **Full build:** - Before: ~26s total - After: ~22.5s total (~13% faster) ## Regression Risk ⚠️ **Medium risk** - Changing the compiler from tsc to tsgo for production builds: 1. **TypeScript 7 preview**: `@typescript/native-preview` is pre-release software (v7.0.0-dev) 2. **Different code generator**: While type checking is identical, the emitted JavaScript may have subtle differences 3. **Platform-specific binaries**: Relies on Go-based native binaries for darwin/linux/win32 across x64/arm64 4. **Path alias resolution**: Still requires `tsc-alias` post-processing (tsgo doesn't resolve `@/` imports) **Mitigation:** - CI tests run on both macOS and Linux - Integration tests verify IPC communication paths - E2E tests verify full application behavior - Build is deterministic (no conditional branches) **Rollback plan:** If issues arise, revert to `tsc` by changing one line in Makefile (line 77). ## Changes - **Updated `Makefile` build-main target**: Uses tsgo directly, no fallback branches - **Updated `Makefile` typecheck target**: Removed tsc fallback (already had branch from PR #260) - **Added build reproducibility guidelines**: Documents why branches are avoided in build targets - **Requires tsgo**: Builds fail fast if tsgo missing (in devDependencies, always available) ## Investigation Findings Analyzed every component of the build toolchain to maximize tsgo usage: | Component | Current Tool | Can Use tsgo? | Status | |-----------|--------------|---------------|--------| | Main process build | tsc | ✅ Yes | ✅ Implemented | | Renderer build | Vite+esbuild | ❌ No | N/A (Vite architecture) | | Preload build | bun | ❌ No | N/A (already fast) | | Type checking | tsgo | ✅ Yes | ✅ Done (PR #260) | | Dev watch (main) | tsgo -w | ✅ Yes | ✅ Done (PR #260) | **Key findings:** 1. **Path alias resolution**: tsgo doesn't resolve `@/` imports, so `tsc-alias` still required (~0.7s overhead, acceptable) 2. **Vite can't use tsgo**: Different compilation model (esbuild + HMR + bundling) 3. **Main build time dominated by Vite**: ~21s for renderer vs ~0.2s for main process **Conclusion:** We've maximized tsgo usage. The remaining build time (~21s Vite renderer compilation) cannot be optimized with tsgo due to architectural constraints. ## Build Reproducibility Removed all conditional branches (if/else fallbacks) from build targets. Builds now fail fast with clear errors if dependencies are missing, rather than silently using different compilers. Added to Makefile header: > **AVOID CONDITIONAL BRANCHES (if/else) IN BUILD TARGETS AT ALL COSTS.** > Branches reduce reproducibility - builds should fail fast with clear errors if dependencies are missing, not silently fall back to different behavior. ## Testing - ✅ Full build succeeds: `make build` - ✅ Type checking works: `make typecheck` - ✅ No unresolved `@/` imports in compiled output - ✅ Dev watch works: `make dev` - ⏳ CI checks (static, integration, e2e) pending _Generated with `cmux`_
1 parent 1200458 commit 3c1c4fe

File tree

1 file changed

+13
-12
lines changed

1 file changed

+13
-12
lines changed

Makefile

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
#
1818
# Adding New Targets:
1919
# Add `## Description` after the target to make it appear in `make help`
20+
#
21+
# Build Reproducibility:
22+
# AVOID CONDITIONAL BRANCHES (if/else) IN BUILD TARGETS AT ALL COSTS.
23+
# Branches reduce reproducibility - builds should fail fast with clear errors
24+
# if dependencies are missing, not silently fall back to different behavior.
2025

2126
# Include formatting rules
2227
include fmt.mk
@@ -31,6 +36,9 @@ include fmt.mk
3136
.PHONY: ensure-deps
3237
.PHONY: check-eager-imports check-bundle-size check-startup
3338

39+
# Build tools
40+
TSGO := bun run node_modules/@typescript/native-preview/bin/tsgo.js
41+
3442
TS_SOURCES := $(shell find src -type f \( -name '*.ts' -o -name '*.tsx' \))
3543

3644
# Default target
@@ -56,7 +64,7 @@ help: ## Show this help message
5664
## Development
5765
dev: node_modules/.installed build-main ## Start development server (Vite + tsgo watcher for 10x faster type checking)
5866
@bun x concurrently -k \
59-
"bun x concurrently \"bun run node_modules/@typescript/native-preview/bin/tsgo.js -w -p tsconfig.main.json\" \"bun x tsc-alias -w -p tsconfig.main.json\"" \
67+
"bun x concurrently \"$(TSGO) -w -p tsconfig.main.json\" \"bun x tsc-alias -w -p tsconfig.main.json\"" \
6068
"vite"
6169

6270
start: node_modules/.installed build-main build-preload build-static ## Build and start Electron app
@@ -69,7 +77,7 @@ build-main: node_modules/.installed dist/main.js ## Build main process
6977

7078
dist/main.js: src/version.ts tsconfig.main.json tsconfig.json $(TS_SOURCES)
7179
@echo "Building main process..."
72-
@NODE_ENV=production bun x tsc -p tsconfig.main.json
80+
@NODE_ENV=production $(TSGO) -p tsconfig.main.json
7381
@NODE_ENV=production bun x tsc-alias -p tsconfig.main.json
7482

7583
build-preload: node_modules/.installed dist/preload.js ## Build preload script
@@ -136,16 +144,9 @@ lint-fix: node_modules/.installed ## Run linter with --fix
136144
@./scripts/lint.sh --fix
137145

138146
typecheck: node_modules/.installed src/version.ts ## Run TypeScript type checking (uses tsgo for 10x speedup)
139-
@if [ -f "node_modules/@typescript/native-preview/bin/tsgo.js" ]; then \
140-
bun x concurrently -g \
141-
"bun run node_modules/@typescript/native-preview/bin/tsgo.js --noEmit" \
142-
"bun run node_modules/@typescript/native-preview/bin/tsgo.js --noEmit -p tsconfig.main.json"; \
143-
else \
144-
echo "⚠️ tsgo not found, falling back to tsc (slower)"; \
145-
bun x concurrently -g \
146-
"tsc --noEmit" \
147-
"tsc --noEmit -p tsconfig.main.json"; \
148-
fi
147+
@bun x concurrently -g \
148+
"$(TSGO) --noEmit" \
149+
"$(TSGO) --noEmit -p tsconfig.main.json"
149150

150151
## Testing
151152
test-integration: node_modules/.installed ## Run all tests (unit + integration)

0 commit comments

Comments
 (0)