20 KiB
Build Pattern Conversion Plan
Author: Matthew Raymer Date: 2025-07-09 Status: PLANNING - Ready for Implementation
Overview
Convert TimeSafari's build instruction pattern from the current script-based
approach to a new Vite mode
-based pattern that provides better environment
management and consistency across all build targets.
Why Vite Mode Instead of NODE_ENV?
Vite's Native Mode System
Vite is designed to work with mode
, which:
- Determines the
.env
file to load (e.g..env.production
,.env.test
, etc.) - Is passed to
defineConfig(({ mode }) => {...})
invite.config.ts
- Is used to set behavior for dev/prod/test at config level
- Provides better integration with Vite's build system
NODE_ENV Limitations
NODE_ENV
is legacy from Webpack-era tooling:
- You can't change
NODE_ENV
manually and expect Vite to adapt - Vite does not map
NODE_ENV
back tomode
- It's redundant with
mode
and might conflict with assumptions - Limited integration with Vite's environment loading system
Usage Pattern
# Correct: Use Vite's mode system
vite build --mode production
vite build --mode development
vite build --mode test
# Only if third-party libraries require NODE_ENV
NODE_ENV=production vite build --mode production
Development vs Build Environments
Development Environment:
- Build with defaults:
npm run build:*
- Uses--mode development
by default - Purpose: Development builds for testing and debugging
- Output: Bundled files with development optimizations
Testing/Production Environments:
- Build with explicit mode:
npm run build:* -- --mode test/production
- Purpose: Validate and deploy the bundled application
- Output: Optimized, bundled files for specific environment
Mode Override Behavior
How --mode
Override Works:
# Base script (no hardcoded mode)
"build:electron": "vite build --config vite.config.electron.mts"
# Development (uses Vite's default: --mode development)
npm run build:electron
# Executes: vite build --config vite.config.electron.mts
# Testing (explicitly overrides with --mode test)
npm run build:electron -- --mode test
# Executes: vite build --config vite.config.electron.mts --mode test
# Production (explicitly overrides with --mode production)
npm run build:electron -- --mode production
# Executes: vite build --config vite.config.electron.mts --mode production
Key Points:
- Base scripts have no hardcoded
--mode
to allow override npm run build:electron
defaults to--mode development
npm run build:electron -- --mode test
overrides to--mode test
- Vite uses the last
--mode
argument if multiple are provided
Capacitor Platform-Specific Commands
Capacitor requires platform-specific sync commands after building:
# General sync (copies web assets to all platforms)
npm run build:capacitor && npx cap sync
# Platform-specific sync
npm run build:capacitor && npx cap sync android
npm run build:capacitor && npx cap sync ios
# Environment-specific with platform sync
npm run build:capacitor -- --mode production && npx cap sync android
npm run build:capacitor -- --mode development && npx cap sync ios
Docker Build Commands
Docker builds include both Vite asset generation and Docker image creation:
# General Docker build (Vite build + Docker image)
npm run build:web:docker
# Environment-specific Docker builds
npm run build:web:docker:test # Test environment + Docker image
npm run build:web:docker:prod # Production environment + Docker image
# Manual mode overrides for Docker builds
npm run build:web:docker -- --mode test
npm run build:web:docker -- --mode production
Docker Build Process:
- Vite Build: Creates optimized web assets with environment-specific variables
- Docker Build: Creates Docker image using
Dockerfile
in project root - Image Tagging: Images are tagged as
timesafari-web
for consistent management
Key Features:
- Complete end-to-end Docker workflow in single command
- Environment-aware builds (test/production configurations)
- Consistent image tagging for deployment
- Mode override flexibility for custom environments
Electron Platform-Specific Commands
Electron requires platform-specific build commands after the Vite build:
# General Electron build (Vite build only)
npm run build:electron
# Platform-specific builds
npm run build:electron:windows # Windows executable
npm run build:electron:mac # macOS app bundle
npm run build:electron:linux # Linux executable
# Package-specific builds
npm run build:electron:appimage # Linux AppImage
npm run build:electron:dmg # macOS DMG installer
# Environment-specific builds
npm run build:electron -- --mode development
npm run build:electron -- --mode test
npm run build:electron -- --mode production
# Environment-specific with platform builds
npm run build:electron:windows -- --mode development
npm run build:electron:windows -- --mode test
npm run build:electron:windows -- --mode production
npm run build:electron:mac -- --mode development
npm run build:electron:mac -- --mode test
npm run build:electron:mac -- --mode production
npm run build:electron:linux -- --mode development
npm run build:electron:linux -- --mode test
npm run build:electron:linux -- --mode production
# Environment-specific with package builds
npm run build:electron:appimage -- --mode development
npm run build:electron:appimage -- --mode test
npm run build:electron:appimage -- --mode production
npm run build:electron:dmg -- --mode development
npm run build:electron:dmg -- --mode test
npm run build:electron:dmg -- --mode production
Current State Analysis
Existing Build Scripts
- Web:
build:web
- Uses vite.config.web.mts - Capacitor:
build:capacitor
- Uses vite.config.capacitor.mts- Android:
build:android
- Shell script wrapper - iOS:
build:ios
- Shell script wrapper
- Android:
- Electron:
build:electron
- Uses vite.config.electron.mts- Windows:
build:electron:windows
- Windows executable - macOS:
build:electron:mac
- macOS app bundle - Linux:
build:electron:linux
- Linux executable - AppImage:
build:electron:appimage
- Linux AppImage - DMG:
build:electron:dmg
- macOS DMG installer
- Windows:
Current package.json
Scripts
{
"build:capacitor": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode capacitor --config vite.config.capacitor.mts",
"build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts",
"build:electron": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode electron --config vite.config.electron.mts"
}
Target Pattern
New Vite Mode-Based Pattern
# Development builds (defaults to --mode development)
npm run build:web-dev
npm run build:capacitor-dev
npm run build:electron-dev
# Testing builds (bundle required)
npm run build:web -- --mode test
npm run build:capacitor -- --mode test && npx cap sync
npm run build:electron -- --mode test
# Production builds (bundle required)
npm run build:web -- --mode production
npm run build:capacitor -- --mode production && npx cap sync
npm run build:electron -- --mode production
# Docker builds
npm run build:web:docker -- --mode test
npm run build:web:docker -- --mode production
# Docker environment-specific builds
npm run build:web:docker:test
npm run build:web:docker:prod
# Capacitor platform-specific builds
npm run build:capacitor:android -- --mode test
npm run build:capacitor:android -- --mode production
npm run build:capacitor:ios -- --mode test
npm run build:capacitor:ios -- --mode production
# Electron platform-specific builds
npm run build:electron:windows -- --mode test
npm run build:electron:windows -- --mode production
npm run build:electron:mac -- --mode test
npm run build:electron:mac -- --mode production
npm run build:electron:linux -- --mode test
npm run build:electron:linux -- --mode production
# Electron package-specific builds
npm run build:electron:appimage -- --mode test
npm run build:electron:appimage -- --mode production
npm run build:electron:dmg -- --mode test
npm run build:electron:dmg -- --mode production
New package.json
Scripts Structure
{
"build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite --mode development --config vite.config.web.mts",
"build:web:dev": "npm run build:web",
"build:web:build": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode development --config vite.config.web.mts",
"build:web:test": "npm run build:web:build -- --mode test",
"build:web:prod": "npm run build:web:build -- --mode production",
"build:web:docker": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts && docker build -t timesafari-web .",
"build:web:docker:test": "npm run build:web:docker -- --mode test",
"build:web:docker:prod": "npm run build:web:docker -- --mode production",
"build:capacitor": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode capacitor --config vite.config.capacitor.mts",
"build:capacitor-dev": "npm run build:capacitor",
"build:capacitor:sync": "npm run build:capacitor && npx cap sync",
"build:capacitor:android": "npm run build:capacitor:sync && npx cap sync android",
"build:capacitor:ios": "npm run build:capacitor:sync && npx cap sync ios",
"build:electron": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.electron.mts",
"build:electron:dev": "npm run build:electron && cd electron && npm run electron:start",
"build:electron:windows": "npm run build:electron && cd electron && npm run build:windows",
"build:electron:mac": "npm run build:electron && cd electron && npm run build:mac",
"build:electron:linux": "npm run build:electron && cd electron && npm run build:linux",
"build:electron:appimage": "npm run build:electron:linux && cd electron && npm run build:appimage",
"build:electron:dmg": "npm run build:electron:mac && cd electron && npm run build:dmg"
}
Implementation Plan
Phase 1: Environment Configuration (Day 1)
1.1 Update Vite Configurations
- vite.config.web.mts: Add mode-based configuration
- vite.config.capacitor.mts: Add mode-based configuration
- vite.config.electron.mts: Add mode-based configuration
- vite.config.common.mts: Add environment-specific variables
1.2 Environment Variables Setup
- Create
.env.development
file for development settings - Create
.env.test
file for testing settings - Create
.env.production
file for production settings - Update
.env.example
with new pattern
1.3 Environment Detection Logic
// vite.config.common.mts
export default defineConfig(({ mode }) => {
const getEnvironmentConfig = (mode: string) => {
switch (mode) {
case 'production':
return { /* production settings */ };
case 'test':
return { /* testing settings */ };
default:
return { /* development settings */ };
}
};
return {
define: {
__DEV__: mode === 'development',
__TEST__: mode === 'test',
__PROD__: mode === 'production'
},
// ... other config
};
});
Phase 2: Package.json Scripts Update (Day 1)
2.1 Web Build Scripts
{
"build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts",
"build:web-dev": "npm run build:web",
"build:web-test": "npm run build:web -- --mode test",
"build:web-prod": "npm run build:web -- --mode production"
}
2.2 Capacitor Build Scripts
{
"build:capacitor": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode capacitor --config vite.config.capacitor.mts",
"build:capacitor-dev": "npm run build:capacitor",
"build:capacitor:sync": "npm run build:capacitor && npx cap sync",
"build:capacitor:android": "npm run build:capacitor:sync && npx cap sync android",
"build:capacitor:ios": "npm run build:capacitor:sync && npx cap sync ios",
"build:capacitor-test": "npm run build:capacitor -- --mode test && npx cap sync",
"build:capacitor-prod": "npm run build:capacitor -- --mode production && npx cap sync",
"build:capacitor:android-test": "npm run build:capacitor -- --mode test && npx cap sync android",
"build:capacitor:android-prod": "npm run build:capacitor -- --mode production && npx cap sync android",
"build:capacitor:ios-test": "npm run build:capacitor -- --mode test && npx cap sync ios",
"build:capacitor:ios-prod": "npm run build:capacitor -- --mode production && npx cap sync ios"
}
2.3 Electron Build Scripts
{
"build:electron": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.electron.mts",
"build:electron-dev": "npm run build:electron",
"build:electron:windows": "npm run build:electron && cd electron && npm run build:windows",
"build:electron:mac": "npm run build:electron && cd electron && npm run build:mac",
"build:electron:linux": "npm run build:electron && cd electron && npm run build:linux",
"build:electron:appimage": "npm run build:electron:linux && cd electron && npm run build:appimage",
"build:electron:dmg": "npm run build:electron:mac && cd electron && npm run build:dmg",
"build:electron-test": "npm run build:electron -- --mode test",
"build:electron-prod": "npm run build:electron -- --mode production",
"build:electron:windows-test": "npm run build:electron -- --mode test && cd electron && npm run build:windows",
"build:electron:windows-prod": "npm run build:electron -- --mode production && cd electron && npm run build:windows",
"build:electron:mac-dev": "npm run build:electron -- --mode development && cd electron && npm run build:mac",
"build:electron:mac-test": "npm run build:electron -- --mode test && cd electron && npm run build:mac",
"build:electron:mac-prod": "npm run build:electron -- --mode production && cd electron && npm run build:mac",
"build:electron:linux-test": "npm run build:electron -- --mode test && cd electron && npm run build:linux",
"build:electron:linux-prod": "npm run build:electron -- --mode production && cd electron && npm run build:linux"
}
2.4 Docker Build Scripts
{
"build:web:docker": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts && docker build -t timesafari-web .",
"build:web:docker:test": "npm run build:web:docker -- --mode test",
"build:web:docker:prod": "npm run build:web:docker -- --mode production"
}
Docker Build Features:
- Complete Vite build + Docker image creation workflow
- Environment-specific configurations (test/production)
- Consistent image tagging (
timesafari-web
) - Mode override flexibility for custom environments
Phase 3: Shell Script Updates (Day 2)
3.1 Update build-electron.sh
- Add mode-based environment support
- Update environment loading logic
- Add environment-specific build paths
- Update logging to show environment
3.2 Update build-android.sh
- Add mode-based environment support
- Update environment detection
- Add environment-specific configurations
3.3 Update build-ios.sh
- Add mode-based environment support
- Update environment detection
- Add environment-specific configurations
Phase 4: Documentation Updates (Day 2)
4.1 Update BUILDING.md
- Document new Vite mode-based pattern
- Update build instructions
- Add environment-specific examples
- Update troubleshooting section
4.2 Update scripts/README.md
- Document new Vite mode-based build patterns
- Update usage examples
- Add environment configuration guide
4.3 Update CI/CD Documentation
- Update GitHub Actions workflows
- Update Docker build instructions
- Update deployment guides
Phase 5: Testing & Validation (Day 3)
5.1 Environment Testing
- Test dev environment builds
- Test test environment builds
- Test prod environment builds
- Validate environment variables
5.2 Platform Testing
- Test web builds across environments
- Test capacitor builds across environments
- Test capacitor android sync across environments
- Test capacitor ios sync across environments
- Test electron builds across environments
- Test electron windows builds across environments
- Test electron mac builds across environments
- Test electron linux builds across environments
- Test electron appimage builds across environments
- Test electron dmg builds across environments
- Test docker builds across environments
- Test docker image creation and tagging
- Test docker environment-specific configurations
5.3 Integration Testing
- Test with existing CI/CD pipelines
- Test with existing deployment scripts
- Test with existing development workflows
Environment-Specific Configurations
Development Environment (--mode development)
{
VITE_API_URL: 'http://localhost:3000',
VITE_DEBUG: 'true',
VITE_LOG_LEVEL: 'debug',
VITE_ENABLE_DEV_TOOLS: 'true'
}
Testing Environment (--mode test)
{
VITE_API_URL: 'https://test-api.timesafari.com',
VITE_DEBUG: 'false',
VITE_LOG_LEVEL: 'info',
VITE_ENABLE_DEV_TOOLS: 'false'
}
Production Environment (--mode production)
{
VITE_API_URL: 'https://api.timesafari.com',
VITE_DEBUG: 'false',
VITE_LOG_LEVEL: 'warn',
VITE_ENABLE_DEV_TOOLS: 'false'
}
Migration Strategy
Backward Compatibility
- Keep existing script names as aliases
- Add deprecation warnings for old scripts
- Maintain existing CI/CD compatibility
- Provide migration guide for users
Gradual Rollout
- Week 1: Implement new scripts alongside existing ones
- Week 2: Update CI/CD to use new pattern
- Week 3: Update documentation and guides
- Week 4: Deprecate old scripts with warnings
Success Metrics
Technical Metrics
- All builds work with Vite mode-based pattern
- Environment variables properly loaded
- Build artifacts correctly generated
- No regression in existing functionality
Process Metrics
- Reduced build script complexity
- Improved environment management
- Better developer experience
- Consistent build patterns
Risk Assessment
Low Risk
- Environment variable changes
- Package.json script updates
- Documentation updates
Medium Risk
- Vite configuration changes (mode-based)
- Shell script modifications
- CI/CD pipeline updates
High Risk
- Breaking existing build processes
- Environment-specific bugs
- Deployment failures
Rollback Plan
Immediate Rollback
- Revert package.json changes
- Restore original vite configs
- Restore original shell scripts
Gradual Rollback
- Keep old scripts as primary
- Use new scripts as experimental
- Gather feedback before full migration
Timeline
Day 1: Foundation
- Environment configuration setup
- Package.json script updates
- Basic testing
Day 2: Integration
- Shell script updates
- Documentation updates
- Integration testing
Day 3: Validation
- Comprehensive testing
- Performance validation
- Documentation review
Day 4: Deployment
- CI/CD updates
- Production validation
- User communication
Next Steps
- Review and approve plan
- Set up development environment
- Begin Phase 1 implementation
- Create test cases
- Start implementation
Status: Ready for implementation Priority: Medium Estimated Effort: 3-4 days Dependencies: None Stakeholders: Development team, DevOps team