You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

371 lines
11 KiB

#!/bin/bash
# build-web.sh
# Author: Matthew Raymer
# Description: Web build script for TimeSafari application
# This script handles the complete web build process including cleanup,
# environment setup, Vite build, and optional Docker containerization.
#
# Usage:
# ./scripts/build-web.sh # Development build
# ./scripts/build-web.sh --dev # Development build (explicit)
# ./scripts/build-web.sh --test # Test environment build
# ./scripts/build-web.sh --prod # Production environment build
# ./scripts/build-web.sh --docker # Build with Docker containerization
# ./scripts/build-web.sh --docker:test # Test environment + Docker
# ./scripts/build-web.sh --docker:prod # Production environment + Docker
# ./scripts/build-web.sh --serve # Build and serve locally
# ./scripts/build-web.sh --help # Show help
# ./scripts/build-web.sh --verbose # Enable verbose logging
#
# NPM Script Equivalents:
# npm run build:web # Development build
# npm run build:web:test # Test environment build
# npm run build:web:prod # Production environment build
# npm run build:web:docker # Docker build
# npm run build:web:docker:test # Test Docker build
# npm run build:web:docker:prod # Production Docker build
#
# Exit Codes:
# 1 - Web cleanup failed
# 2 - Environment setup failed
# 3 - Vite build failed
# 4 - Docker build failed
# 5 - Serve command failed
# 6 - Invalid build mode
# Exit on any error
set -e
# Source common utilities
source "$(dirname "$0")/common.sh"
# Default values
BUILD_MODE="development"
BUILD_ACTION="build"
DOCKER_BUILD=false
SERVE_BUILD=false
# Function to show usage
show_usage() {
cat << EOF
Usage: $0 [OPTIONS]
OPTIONS:
--dev, --development Build for development environment (default)
--test Build for test environment
--prod, --production Build for production environment
--docker Build and create Docker container
--docker:test Build for test environment and create Docker container
--docker:prod Build for production environment and create Docker container
--serve Build and serve locally
--help Show this help message
--verbose Enable verbose logging
--env Show environment variables
EXAMPLES:
$0 # Development build
$0 --test # Test environment build
$0 --prod # Production environment build
$0 --docker # Development + Docker
$0 --docker:test # Test + Docker
$0 --docker:prod # Production + Docker
$0 --serve # Build and serve
BUILD MODES:
development: Starts Vite development server with hot reload (default)
test: Optimized for testing with minimal minification
production: Optimized for production with full minification and optimization
EOF
}
# Function to parse web-specific arguments
parse_web_args() {
while [[ $# -gt 0 ]]; do
case $1 in
--dev|--development)
BUILD_MODE="development"
shift
;;
--test)
BUILD_MODE="test"
shift
;;
--prod|--production)
BUILD_MODE="production"
shift
;;
--docker)
DOCKER_BUILD=true
shift
;;
--docker:test)
BUILD_MODE="test"
DOCKER_BUILD=true
shift
;;
--docker:prod)
BUILD_MODE="production"
DOCKER_BUILD=true
shift
;;
--serve)
SERVE_BUILD=true
shift
;;
--help)
show_usage
exit 0
;;
--verbose)
VERBOSE=true
shift
;;
--env)
print_env_vars "VITE_"
exit 0
;;
*)
log_warn "Unknown option: $1"
shift
;;
esac
done
}
# Function to validate web build environment
validate_web_environment() {
log_info "Validating web build environment..."
# Check if Node.js is available
if ! check_command "node"; then
log_error "Node.js is required but not installed"
exit 2
fi
# Check if npm is available
if ! check_command "npm"; then
log_error "npm is required but not installed"
exit 2
fi
# Check if Vite is available
if ! check_command "npx"; then
log_error "npx is required but not installed"
exit 2
fi
# Check if package.json exists
if ! check_file "package.json"; then
log_error "package.json not found in current directory"
exit 2
fi
log_success "Web build environment validated"
}
# Function to setup web-specific environment
setup_web_environment() {
log_info "Setting up web environment for $BUILD_MODE mode..."
# Set NODE_ENV based on build mode
case $BUILD_MODE in
"production")
export NODE_ENV="production"
;;
"test")
export NODE_ENV="test"
;;
"development"|*)
export NODE_ENV="development"
;;
esac
# Load environment-specific .env file if it exists
local env_file=".env.$BUILD_MODE"
if [ -f "$env_file" ]; then
load_env_file "$env_file"
else
log_debug "No $env_file file found, using default environment"
fi
# Load .env file if it exists (fallback)
if [ -f ".env" ]; then
load_env_file ".env"
fi
log_success "Web environment configured for $BUILD_MODE mode"
log_debug "NODE_ENV=$NODE_ENV"
}
# Function to execute Vite build
execute_vite_build() {
local mode="$1"
log_info "Executing Vite build for $mode mode..."
# Construct Vite build command
local vite_cmd="VITE_GIT_HASH=\$(git log -1 --pretty=format:%h) npx vite build --config vite.config.web.mts"
# Add mode if not development (development is default)
if [ "$mode" != "development" ]; then
vite_cmd="$vite_cmd --mode $mode"
fi
log_debug "Vite command: $vite_cmd"
if ! measure_time eval "$vite_cmd"; then
log_error "Vite build failed for $mode mode!"
exit 3
fi
log_success "Vite build completed for $mode mode"
}
# Function to execute Docker build
execute_docker_build() {
local mode="$1"
log_info "Executing Docker build for $mode mode..."
# Build Docker image with appropriate tags
local docker_cmd="docker build"
local image_tag="timesafari-web"
# Add build arguments
docker_cmd="$docker_cmd --build-arg BUILD_MODE=$mode"
docker_cmd="$docker_cmd --build-arg NODE_ENV=$NODE_ENV"
# Add image tag
docker_cmd="$docker_cmd -t $image_tag:$mode"
docker_cmd="$docker_cmd -t $image_tag:latest"
# Add context
docker_cmd="$docker_cmd ."
log_debug "Docker command: $docker_cmd"
if ! measure_time eval "$docker_cmd"; then
log_error "Docker build failed for $mode mode!"
exit 4
fi
log_success "Docker build completed for $mode mode"
log_info "Docker image available as: $image_tag:$mode"
}
# Function to start Vite development server
start_dev_server() {
log_info "Starting Vite development server..."
# Construct Vite dev server command
local vite_cmd="VITE_GIT_HASH=\$(git log -1 --pretty=format:%h) npx vite --config vite.config.web.mts"
# Add mode if specified (though development is default)
if [ "$BUILD_MODE" != "development" ]; then
vite_cmd="$vite_cmd --mode $BUILD_MODE"
fi
log_debug "Vite dev server command: $vite_cmd"
log_info "Starting development server on http://localhost:8080"
# Start the development server (this will block and run the server)
eval "$vite_cmd"
}
# Function to serve build locally
serve_build() {
log_info "Serving build locally..."
# Check if dist directory exists
if [ ! -d "dist" ]; then
log_error "dist directory not found. Build must be completed first."
exit 5
fi
# Use a simple HTTP server to serve the build
if command -v python3 &> /dev/null; then
log_info "Starting Python HTTP server on port 8080..."
cd dist && python3 -m http.server 8080
elif command -v python &> /dev/null; then
log_info "Starting Python HTTP server on port 8080..."
cd dist && python -m SimpleHTTPServer 8080
elif command -v npx &> /dev/null; then
log_info "Starting npx serve on port 8080..."
npx serve -s dist -l 8080
else
log_error "No suitable HTTP server found. Install Python or npx serve."
exit 5
fi
}
# Parse command line arguments
parse_web_args "$@"
# Print build header
print_header "TimeSafari Web Build Process"
log_info "Starting web build process at $(date)"
log_info "Build mode: $BUILD_MODE"
log_info "Docker build: $DOCKER_BUILD"
log_info "Serve build: $SERVE_BUILD"
# Validate environment
validate_web_environment
# Setup environment for web build
setup_build_env "web"
# Setup application directories
setup_app_directories
# Setup web-specific environment
setup_web_environment
# Handle different build modes
if [ "$BUILD_MODE" = "development" ] && [ "$DOCKER_BUILD" = false ] && [ "$SERVE_BUILD" = false ]; then
# Development mode: Start dev server
log_info "Development mode detected - starting development server"
start_dev_server
# Note: start_dev_server doesn't return, it runs the server
elif [ "$SERVE_BUILD" = true ]; then
# Serve mode: Build then serve
log_info "Serve mode detected - building then serving"
# Step 1: Clean dist directory
log_info "Cleaning dist directory..."
clean_build_artifacts "dist"
# Step 2: Execute Vite build
safe_execute "Vite build for $BUILD_MODE mode" "execute_vite_build $BUILD_MODE" || exit 3
# Step 3: Serve the build
log_info "Starting local server..."
serve_build
# Note: serve_build doesn't return, it starts the server
else
# Build mode: Build (and optionally Docker)
log_info "Build mode detected - building for $BUILD_MODE"
# Step 1: Clean dist directory
log_info "Cleaning dist directory..."
clean_build_artifacts "dist"
# Step 2: Execute Vite build
safe_execute "Vite build for $BUILD_MODE mode" "execute_vite_build $BUILD_MODE" || exit 3
# Step 3: Execute Docker build if requested
if [ "$DOCKER_BUILD" = true ]; then
safe_execute "Docker build for $BUILD_MODE mode" "execute_docker_build $BUILD_MODE" || exit 4
fi
# Print build summary
log_success "Web build completed successfully!"
log_info "Build output available in: dist/"
if [ "$DOCKER_BUILD" = true ]; then
log_info "Docker image available as: timesafari-web:$BUILD_MODE"
fi
print_footer "Web Build"
# Exit with success
exit 0
fi