Development Server Configuration
Development server configuration in Azu CLI manages the development environment, including hot reloading, file watching, debugging options, and development-specific settings. This enables fast development cycles with automatic rebuilding and reloading.
Overview
The development server provides:
Hot Reloading: Automatic rebuild and restart on file changes
File Watching: Monitor source files for changes
Live Reloading: Browser refresh on template changes
Debug Mode: Enhanced debugging capabilities
Development Tools: Built-in development utilities
Development Server Configuration Structure
Base Development Configuration
# config/development.yml
development:
# Server settings
server:
host: <%= ENV["AZU_HOST"] || "localhost" %>
port: <%= ENV["AZU_PORT"] || 3000 %>
workers: 1
backlog: 1024
# Hot reloading
hot_reload:
enabled: true
rebuild_on_change: true
restart_on_change: true
browser_reload: true
# File watching
file_watcher:
enabled: true
watch_paths:
- src/
- config/
- public/templates/
ignored_paths:
- .git/
- node_modules/
- .crystal/
- bin/
- tmp/
- log/
ignored_extensions:
- .tmp
- .swp
- .swo
# Compilation
compilation:
incremental: true
parallel: true
cache_dir: .crystal/
debug: true
warnings: true
# Debugging
debugging:
enabled: true
port: 5005
suspend: false
log_level: debug
# Development tools
tools:
inspector: true
profiler: true
memory_tracker: true
performance_monitor: true
Server Configuration
Basic Server Settings
# Server configuration
development:
server:
# Network settings
host: localhost
port: 3000
workers: 1
backlog: 1024
# SSL/TLS (for HTTPS in development)
ssl:
enabled: false
cert_file: cert.pem
key_file: key.pem
# HTTP settings
http:
keep_alive: true
timeout: 30
max_request_size: 10MB
# CORS (for API development)
cors:
enabled: true
origins: ["http://localhost:3000", "http://localhost:3001"]
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
headers: ["Content-Type", "Authorization"]
Advanced Server Settings
# Advanced server configuration
development:
server:
# Performance tuning
performance:
tcp_nodelay: true
reuse_address: true
keep_alive_timeout: 5
# Security headers
security_headers:
enabled: true
headers:
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-XSS-Protection: "1; mode=block"
Referrer-Policy: strict-origin-when-cross-origin
# Rate limiting
rate_limiting:
enabled: false
requests_per_minute: 100
burst_size: 10
# Compression
compression:
enabled: true
level: 6
types:
- text/html
- text/css
- application/javascript
- application/json
Hot Reloading Configuration
Hot Reload Settings
# Hot reload configuration
development:
hot_reload:
# Enable/disable hot reloading
enabled: true
# Rebuild settings
rebuild_on_change: true
restart_on_change: true
browser_reload: true
# Rebuild triggers
triggers:
# Crystal files
crystal_files: true
# Configuration files
config_files: true
# Template files
template_files: true
# Asset files
asset_files: false
# Rebuild behavior
behavior:
# Wait time before rebuild
debounce_ms: 100
# Maximum rebuild frequency
max_rebuilds_per_minute: 60
# Show rebuild progress
show_progress: true
# Show rebuild errors
show_errors: true
# Browser integration
browser:
# Auto-reload browser
auto_reload: true
# Reload delay
reload_delay: 500
# Reload strategy
strategy: "full" # full, partial, smart
Hot Reload Implementation
# Hot reload implementation
class HotReloader
def initialize(config : DevelopmentConfig)
@config = config
@file_watcher = FileWatcher.new(config.file_watcher)
@browser_reloader = BrowserReloader.new(config.hot_reload.browser)
@compiler = Compiler.new(config.compilation)
end
def start
@file_watcher.watch do |changed_files|
handle_file_changes(changed_files)
end
end
private def handle_file_changes(files : Array(String))
return unless @config.hot_reload.enabled
# Debounce changes
sleep(@config.hot_reload.behavior.debounce_ms.milliseconds)
# Determine rebuild type
if should_rebuild?(files)
rebuild_application
elsif should_restart?(files)
restart_application
elsif should_reload_browser?(files)
reload_browser
end
end
private def should_rebuild?(files : Array(String)) : Bool
files.any? { |file| file.ends_with?(".cr") || file.ends_with?(".yml") }
end
private def should_restart?(files : Array(String)) : Bool
files.any? { |file| file.includes?("config/") && file.ends_with?(".yml") }
end
private def should_reload_browser?(files : Array(String)) : Bool
files.any? { |file| file.ends_with?(".jinja") || file.ends_with?(".html") }
end
end
File Watching Configuration
File Watcher Settings
# File watcher configuration
development:
file_watcher:
# Enable/disable file watching
enabled: true
# Watch paths
watch_paths:
- src/
- config/
- public/templates/
- public/assets/
# Ignored paths
ignored_paths:
- .git/
- node_modules/
- .crystal/
- bin/
- tmp/
- log/
- spec/
# Ignored file extensions
ignored_extensions:
- .tmp
- .swp
- .swo
- .log
- .pid
# Watch options
options:
# Recursive watching
recursive: true
# Follow symlinks
follow_symlinks: false
# Watch for new files
watch_new_files: true
# Watch for deleted files
watch_deleted_files: true
# Performance settings
performance:
# Polling interval (for systems without inotify)
poll_interval: 1000
# Maximum files to watch
max_files: 10000
# Buffer size for file events
buffer_size: 1024
File Watcher Implementation
# File watcher implementation
class FileWatcher
def initialize(config : FileWatcherConfig)
@config = config
@watched_files = Set(String).new
@callbacks = [] of Proc(Array(String), Nil)
end
def watch(&block : Array(String) -> Nil)
@callbacks << block
spawn do
watch_files
end
end
private def watch_files
# Use system-specific file watching
if FileWatcher.supports_inotify?
watch_with_inotify
else
watch_with_polling
end
end
private def watch_with_inotify
# Use inotify for Linux systems
Inotify.watch(@config.watch_paths) do |event|
handle_file_event(event)
end
end
private def watch_with_polling
# Fallback to polling
loop do
check_for_changes
sleep(@config.performance.poll_interval.milliseconds)
end
end
private def handle_file_event(event : FileEvent)
return if should_ignore?(event.path)
changed_files = [event.path]
notify_callbacks(changed_files)
end
private def should_ignore?(path : String) : Bool
@config.ignored_paths.any? { |ignored| path.includes?(ignored) } ||
@config.ignored_extensions.any? { |ext| path.ends_with?(ext) }
end
private def notify_callbacks(files : Array(String))
@callbacks.each do |callback|
callback.call(files)
end
end
end
Compilation Configuration
Compilation Settings
# Compilation configuration
development:
compilation:
# Compilation mode
mode: incremental
# Performance settings
incremental: true
parallel: true
cache_dir: .crystal/
# Debug settings
debug: true
warnings: true
assertions: true
# Compilation flags
flags:
- --debug
- --warnings
- --no-debug
- --threads 2
# Conditional compilation
defines:
- DEVELOPMENT
- DEBUG
- ENABLE_LOGGING
# Optimization
optimization:
level: 0 # No optimization for fast compilation
strip_symbols: false
# Output settings
output:
directory: bin/
filename: <%= @project_name.underscore %>_dev
static: false
Compiler Implementation
# Compiler implementation
class Compiler
def initialize(config : CompilationConfig)
@config = config
@cache = CompilationCache.new(config.cache_dir)
end
def compile : Bool
Azu::Logger.info("Compiling application...")
start_time = Time.monotonic
# Build command
command = build_compile_command
# Execute compilation
result = Process.run(command, shell: true, error: Process::Redirect::Pipe)
duration = Time.monotonic - start_time
if result.success?
Azu::Logger.info("Compilation successful (#{duration.total_milliseconds}ms)")
true
else
Azu::Logger.error("Compilation failed: #{result.error_message}")
false
end
end
private def build_compile_command : String
parts = ["crystal", "build"]
# Add flags
@config.flags.each { |flag| parts << flag }
# Add defines
@config.defines.each { |define| parts << "-D#{define}" }
# Add output
parts << "-o#{@config.output.directory}/#{@config.output.filename}"
# Add main file
parts << "src/main.cr"
parts.join(" ")
end
end
Debugging Configuration
Debug Settings
# Debugging configuration
development:
debugging:
# Enable/disable debugging
enabled: true
# Debug server settings
server:
port: 5005
host: localhost
suspend: false
# Debug options
options:
# Show debug info
show_debug_info: true
# Show stack traces
show_stack_traces: true
# Show variable values
show_variables: true
# Show call stack
show_call_stack: true
# Logging
logging:
level: debug
show_timestamps: true
show_source_location: true
show_thread_id: true
# Performance profiling
profiling:
enabled: true
cpu_profiling: true
memory_profiling: true
allocation_tracking: true
Debug Implementation
# Debug implementation
class Debugger
def initialize(config : DebuggingConfig)
@config = config
@profiler = Profiler.new(config.profiling)
end
def start
return unless @config.enabled
# Start debug server
start_debug_server
# Start profiler
start_profiler
Azu::Logger.info("Debug mode enabled on port #{@config.server.port}")
end
private def start_debug_server
spawn do
# Start debug server implementation
DebugServer.new(@config.server).start
end
end
private def start_profiler
return unless @config.profiling.enabled
@profiler.start
end
def log_debug(message : String, context : Hash(String, String) = {} of String => String)
return unless @config.enabled
Azu::Logger.debug("[DEBUG] #{message}", context)
end
end
Development Tools Configuration
Development Tools
# Development tools configuration
development:
tools:
# Code inspector
inspector:
enabled: true
port: 3001
auto_open: true
# Performance profiler
profiler:
enabled: true
port: 3002
sampling_rate: 1000
# Memory tracker
memory_tracker:
enabled: true
track_allocations: true
track_gc: true
leak_detection: true
# Performance monitor
performance_monitor:
enabled: true
metrics:
- response_time
- memory_usage
- cpu_usage
- request_count
dashboard_port: 3003
# API documentation
api_docs:
enabled: true
port: 3004
auto_generate: true
include_examples: true
Environment-Specific Configuration
Development Environment
# config/development.yml
development:
server:
host: localhost
port: 3000
hot_reload:
enabled: true
rebuild_on_change: true
browser_reload: true
file_watcher:
enabled: true
watch_paths:
- src/
- config/
- public/templates/
compilation:
incremental: true
debug: true
warnings: true
debugging:
enabled: true
port: 5005
tools:
inspector: true
profiler: true
memory_tracker: true
Test Environment
# config/test.yml
development:
server:
host: localhost
port: 3001
hot_reload:
enabled: false
rebuild_on_change: false
browser_reload: false
file_watcher:
enabled: false
compilation:
incremental: false
debug: false
warnings: false
debugging:
enabled: false
tools:
inspector: false
profiler: false
memory_tracker: false
Development Server Commands
Server Management Commands
# Start development server
azu serve
# Start with custom port
azu serve --port 4000
# Start with custom host
azu serve --host 0.0.0.0
# Disable hot reloading
azu serve --no-reload
# Enable debug mode
azu serve --debug
# Start with profiling
azu serve --profile
# Show server status
azu serve --status
# Stop development server
azu serve --stop
Development Tools Commands
# Open code inspector
azu dev inspector
# Open performance profiler
azu dev profiler
# Open memory tracker
azu dev memory
# Open performance monitor
azu dev monitor
# Generate API documentation
azu dev api-docs
# Show development tools
azu dev tools
Environment Variables
Development Environment Variables
# Server settings
export AZU_HOST="localhost"
export AZU_PORT="3000"
export AZU_WORKERS="1"
# Hot reloading
export AZU_HOT_RELOAD="true"
export AZU_REBUILD_ON_CHANGE="true"
export AZU_BROWSER_RELOAD="true"
# File watching
export AZU_FILE_WATCHER="true"
export AZU_WATCH_PATHS="src/,config/,public/templates/"
# Compilation
export AZU_INCREMENTAL="true"
export AZU_PARALLEL="true"
export AZU_DEBUG="true"
export AZU_WARNINGS="true"
# Debugging
export AZU_DEBUG_MODE="true"
export AZU_DEBUG_PORT="5005"
# Development tools
export AZU_INSPECTOR="true"
export AZU_PROFILER="true"
export AZU_MEMORY_TRACKER="true"
Best Practices
Development Workflow
Hot Reloading: Enable hot reloading for fast development cycles
File Watching: Configure appropriate watch paths and ignored paths
Incremental Compilation: Use incremental compilation for faster builds
Debug Mode: Enable debug mode during development
Development Tools: Use built-in development tools for debugging
Performance
Watch Paths: Limit watch paths to necessary directories
Ignored Paths: Exclude unnecessary directories from watching
Debouncing: Use appropriate debounce times for file changes
Compilation Cache: Enable compilation caching
Parallel Compilation: Use parallel compilation when possible
Debugging
Debug Mode: Enable debug mode for detailed error information
Profiling: Use profiling tools to identify performance bottlenecks
Memory Tracking: Monitor memory usage during development
Logging: Use appropriate log levels for debugging
Error Handling: Implement proper error handling and reporting
Related Documentation
Configuration Overview - General configuration guide
Project Configuration - Project-specific configuration
Database Configuration - Database configuration
Generator Configuration - Code generation configuration
Environment Variables - Environment variable reference
Last updated