vibetunnel/docs/custom-node.md
2025-06-26 23:10:05 +02:00

135 lines
4.9 KiB
Markdown

# Custom Node.js Build
## Motivation
VibeTunnel uses Node.js Single Executable Applications (SEA) to create a standalone terminal server. However, the standard Node.js binary is quite large:
- **Standard Node.js binary**: ~110MB
- **Custom minimal Node.js**: ~43MB (61% reduction)
- **Final executable size**: ~45MB (down from ~105MB)
- **Final app size impact**: Reduces app from ~130MB to ~88MB
We don't need many Node.js features for VibeTunnel:
- No internationalization (ICU) support needed
- No npm package manager in the binary
- No inspector/debugging protocol
- No V8 snapshots or code cache
By building a custom Node.js without these features, we achieve a significantly smaller app bundle while maintaining full functionality.
## Build Behavior
### Debug Mode (Xcode)
- Uses system Node.js for faster iteration
- No custom Node.js compilation required
- Build output shows: `"Debug build - using system Node.js for faster builds"`
- If a custom Node.js was previously built, it will be reused for consistency
### Release Mode (Xcode)
- Automatically builds custom minimal Node.js on first run
- Compilation takes 10-20 minutes but is cached for future builds
- Uses the custom Node.js to create a smaller executable
- Build output shows version and size comparison
## Prerequisites
### Required Build Tools
For optimal build performance, the following tools are required:
- **Ninja**: Build system for faster compilation (significantly faster than Make)
- **ccache**: Compiler cache to speed up rebuilds
#### Installation
- **macOS**: `brew install ninja ccache`
- **Linux**: `apt-get install ninja-build ccache` (or equivalent for your distribution)
The build script will automatically use these tools if available, falling back to Make if Ninja is not found.
## Build Automation
### Release Builds
The release script (`mac/scripts/release.sh`) automatically checks for and builds custom Node.js if needed. You don't need to manually build it before releases.
### Manual Custom Node.js Build
To build the custom Node.js manually (outside of Xcode):
```bash
cd web
node build-custom-node.js --latest
```
This will:
1. Download the latest Node.js source
2. Configure it without unnecessary features
3. Build with optimizations (`-Os`, `-flto`, etc.)
4. Cache the result in `web/.node-builds/`
To use the custom Node.js for building the executable:
```bash
cd web
npm run build -- --custom-node
```
Or directly:
```bash
node build-native.js --custom-node
```
## Build Process Details
### Automatic Detection
The build system automatically searches for custom Node.js builds in `.node-builds/` when `--custom-node` is passed without a path. It finds the most recent build by checking directory modification times.
### Code Signing on macOS
When building the executable:
1. The Node.js binary is injected with our JavaScript code (SEA process)
2. The binary is stripped to remove debug symbols
3. The executable is re-signed with an ad-hoc signature
Note: You may see a warning about "invalidating the code signature" during the strip process - this is expected and harmless since we re-sign immediately after.
## Technical Details
### Features Disabled
- `--without-intl` - Removes internationalization support
- `--without-npm` - Excludes npm from the binary
- `--without-corepack` - Removes package manager wrapper
- `--without-inspector` - Disables debugging protocol
- `--without-node-snapshot` - Skips V8 snapshot (~2-3MB)
- `--without-node-code-cache` - Skips code cache (~1-2MB)
### Optimization Flags
- `-Os` - Optimize for size
- `-flto` - Link-time optimization
- `-ffunction-sections` / `-fdata-sections` - Enable dead code elimination
- `-Wl,-dead_strip` - Remove unused code at link time
### Build Cache
Custom Node.js builds are stored in `web/.node-builds/` and are excluded from git via `.gitignore`. The build system automatically detects and reuses existing builds.
## File Locations
- Build script: `web/build-custom-node.js`
- Native executable builder: `web/build-native.js`
- Xcode integration: `mac/scripts/build-web-frontend.sh`
- Build output: `web/.node-builds/node-v*-minimal/`
- Final executable: `web/native/vibetunnel`
## Troubleshooting
### Custom Node.js not detected
- Ensure the build completed successfully: check for `.node-builds/node-v*-minimal/out/Release/node`
- In Debug mode, the system will use custom Node.js if already built
- In Release mode, it will build custom Node.js automatically if not present
### Code signature warnings
The warning "changes being made to the file will invalidate the code signature" is expected and handled automatically. The build process re-signs the executable after all modifications.
## Known Limitations
- The custom Node.js build process takes 10-20 minutes on first run
- Cross-compilation is not supported - you must build on the target platform
- The custom build excludes some features that may be needed by certain npm packages
- Native module compatibility issues may occur when mixing Node.js versions