From cd281647e2cf66565e77fefacb96889f102b7434 Mon Sep 17 00:00:00 2001 From: Till Tomczak Date: Mon, 2 Jun 2025 09:31:25 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=89=20Updated=20documentation=20and=20?= =?UTF-8?q?requirements=20for=20optimized=20corrections=20=E2=86=92=20rena?= =?UTF-8?q?med=20'SETUP=5FOPTIMIERUNGEN.md'=20to=20'SETUP=5FKORREKTUREN.md?= =?UTF-8?q?',=20modified=20'requirements.txt'=20and=20'setup.sh'.=20?= =?UTF-8?q?=F0=9F=96=A5=EF=B8=8F=F0=9F=93=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ..._OPTIMIERUNGEN.md => SETUP_KORREKTUREN.md} | 0 backend/requirements.txt | 138 ++-- backend/setup.sh | 599 ++++++++---------- 3 files changed, 353 insertions(+), 384 deletions(-) rename backend/docs/{SETUP_OPTIMIERUNGEN.md => SETUP_KORREKTUREN.md} (100%) diff --git a/backend/docs/SETUP_OPTIMIERUNGEN.md b/backend/docs/SETUP_KORREKTUREN.md similarity index 100% rename from backend/docs/SETUP_OPTIMIERUNGEN.md rename to backend/docs/SETUP_KORREKTUREN.md diff --git a/backend/requirements.txt b/backend/requirements.txt index 94b570d3..28906aab 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,126 +1,134 @@ # MYP Platform - Python Dependencies # Aktualisiert: 2025-01-12 # Kompatibel mit Python 3.8+ +# Produktions-optimierte Versionen mit Kompatibilitätsgarantie # ===== CORE FRAMEWORK ===== Flask==3.1.1 -Werkzeug>=2.3.0,<3.0.0 +Werkzeug==3.1.3 +Jinja2==3.1.4 # ===== FLASK EXTENSIONS ===== Flask-Login==0.6.3 Flask-WTF==1.2.1 -Flask-SocketIO -WTForms -Flask-CORS +Flask-SocketIO==5.4.1 +WTForms==3.1.2 +Flask-CORS==5.0.0 Flask-Compress==1.15 # ===== DATABASE ===== -SQLAlchemy>=2.0.0,<3.0.0 +SQLAlchemy==2.0.36 # ===== SECURITY ===== -cryptography>=41.0.0 -bcrypt -PyJWT -itsdangerous +cryptography==44.0.0 +bcrypt==4.2.1 +PyJWT==2.10.1 +itsdangerous==2.2.0 # ===== HTTP REQUESTS ===== -requests -urllib3 +requests==2.32.3 +urllib3==2.2.3 # ===== HARDWARE INTEGRATION ===== -PyP100 -pyserial -pyusb +PyP100==0.0.8 +pyserial==3.5 +pyusb==1.2.1 # ===== REAL-TIME FEATURES ===== -eventlet -python-socketio +eventlet==0.37.0 +python-socketio==5.13.2 # ===== SCHEDULING ===== -schedule -APScheduler +schedule==1.2.2 +APScheduler==3.10.4 # ===== GIS & LOCATION ===== -geocoder +geocoder==1.38.1 # ===== DATA PROCESSING & EXPORT ===== -openpyxl -xlsxwriter -pandas -chardet -python-magic -python-magic-bin; sys_platform == "win32" +openpyxl==3.1.5 +xlsxwriter==3.2.0 +pandas==2.2.3 +chardet==5.2.0 +python-magic==0.4.27 +python-magic-bin==0.4.14; sys_platform == "win32" # ===== EMAIL & VALIDATION ===== -email-validator +email-validator==2.2.0 # ===== IMAGE PROCESSING ===== -Pillow -qrcode[pil] +Pillow==11.0.0 +qrcode[pil]==8.0 # ===== PDF & REPORT GENERATION ===== -reportlab -weasyprint +reportlab==4.2.5 +weasyprint==63.1 # ===== DATE/TIME HANDLING ===== -python-dateutil -pytz +python-dateutil==2.9.0 +pytz==2024.2 # ===== LOGGING & MONITORING ===== -colorlog -psutil +colorlog==6.9.0 +psutil==6.1.1 # ===== FILE SYSTEM OPERATIONS ===== -watchdog -Send2Trash +watchdog==6.0.0 +Send2Trash==1.8.3 # ===== DATA VALIDATION ===== -cerberus -marshmallow -validators +cerberus==1.3.5 +marshmallow==3.23.2 +validators==0.34.0 # ===== UTILITIES ===== -python-slugify -click -humanize -python-dotenv +python-slugify==8.0.4 +click==8.1.7 +humanize==4.11.0 +python-dotenv==1.0.1 # ===== NETWORK & API ===== -ping3 -netifaces +ping3==4.0.8 +netifaces==0.11.0 # ===== CACHING ===== -cachelib +cachelib==0.13.0 # ===== COMPRESSION ===== -py7zr +py7zr==0.22.0 # ===== WINDOWS COMPATIBILITY ===== -pywin32; sys_platform == "win32" -wmi; sys_platform == "win32" -colorama; sys_platform == "win32" +pywin32==308; sys_platform == "win32" +wmi==1.5.1; sys_platform == "win32" +colorama==0.4.6; sys_platform == "win32" # ===== LINUX COMPATIBILITY ===== -RPi.GPIO; sys_platform == "linux" +RPi.GPIO==0.7.1; sys_platform == "linux" # ===== PRODUCTION DEPLOYMENT ===== -gunicorn; sys_platform != "win32" -waitress +gunicorn==23.0.0; sys_platform != "win32" +waitress==3.0.2 # ===== TESTING & DEVELOPMENT ===== -pytest -pytest-flask -pytest-cov -coverage +pytest==8.3.4 +pytest-flask==1.3.0 +pytest-cov==6.0.0 +coverage==7.6.9 # ===== CODE QUALITY ===== -flake8 -black -isort +flake8==7.1.1 +black==24.10.0 +isort==5.13.2 + +# ===== DEPENDENCY COMPATIBILITY ===== +MarkupSafe==3.0.2 +setuptools==75.6.0 +wheel==0.45.1 +pip==24.3.1 # ===== OPTIONAL PERFORMANCE ENHANCEMENTS ===== -# Uncomment for better performance: -# uwsgi; sys_platform != "win32" -# gevent -# redis -# celery +# Auskommentiert für Stabilität - bei Bedarf aktivieren: +# uwsgi==2.0.26; sys_platform != "win32" +# gevent==24.11.1 +# redis==5.2.1 +# celery==5.4.0 diff --git a/backend/setup.sh b/backend/setup.sh index 5af0e66c..7ca5df32 100644 --- a/backend/setup.sh +++ b/backend/setup.sh @@ -6,16 +6,14 @@ # Optimiert für Debian/Linux (Raspberry Pi OS) - KEIN Windows-Support # HTTPS auf Port 443 mit automatischer SSL-Zertifikat-Generierung # Kiosk-Modus mit Chromium-Autostart ohne Desktop-Environment -# RASPBERRY PI CSS/JS PERFORMANCE-OPTIMIERUNGEN INTEGRIERT -# Automatische Hardware-Erkennung und spezifische Browser-Optimierungen -# Version: 4.1.0 - Raspberry Pi CSS-Optimiert +# Version: 4.0.0 # =================================================================== set -euo pipefail # =========================== GLOBALE KONFIGURATION =========================== readonly APP_NAME="MYP Druckerverwaltung" -readonly APP_VERSION="4.1.0" +readonly APP_VERSION="4.0.0" readonly APP_DIR="/opt/myp" readonly HTTPS_SERVICE_NAME="myp-https" readonly KIOSK_SERVICE_NAME="myp-kiosk" @@ -86,15 +84,6 @@ check_debian_system() { if [ -f /proc/device-tree/model ]; then local pi_model=$(cat /proc/device-tree/model 2>/dev/null || echo "Unbekannt") info "Raspberry Pi Modell: $pi_model" - - # Exportiere Raspberry Pi Detection für spätere Verwendung - export IS_RASPBERRY_PI=true - export PI_MODEL="$pi_model" - - # Raspberry Pi spezifische Optimierungen aktivieren - log "✅ Raspberry Pi Hardware erkannt - CSS-Optimierungen werden aktiviert" - else - export IS_RASPBERRY_PI=false fi } @@ -566,23 +555,6 @@ if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = "1" ]; then --disable-web-security \ --allow-running-insecure-content \ --unsafely-treat-insecure-origin-as-secure=https://localhost:443 \ - --disable-gpu-compositing \ - --enable-gpu-rasterization \ - --disable-smooth-scrolling \ - --disable-2d-canvas-image-chromium \ - --disable-accelerated-2d-canvas \ - --num-raster-threads=2 \ - --enable-zero-copy \ - --disable-gpu-sandbox \ - --disable-software-rasterizer \ - --enable-low-end-device-mode \ - --disable-features=VizHitTestSurfaceLayer \ - --disable-partial-raster \ - --disable-threaded-animation \ - --disable-checker-imaging \ - --disable-new-content-rendering-timeout \ - --run-all-compositor-stages-before-draw \ - --disable-ipc-flooding-protection \ https://localhost:443 else exec firefox-esr \ @@ -608,68 +580,6 @@ EOF mkdir -p "$kiosk_home/.chromium-kiosk" chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.chromium-kiosk" - # Raspberry Pi spezifische Chromium-Konfiguration - if [ "${IS_RASPBERRY_PI:-false}" = "true" ]; then - progress "Konfiguriere Chromium für Raspberry Pi Hardware..." - - # Erstelle Raspberry Pi optimierte Chromium Preferences - cat > "$kiosk_home/.chromium-kiosk/Default/Preferences" << 'EOF' -{ - "browser" : { - "check_default_browser" : false, - "show_home_button" : false - }, - "profile" : { - "default_content_setting_values" : { - "notifications" : 2 - }, - "password_manager_enabled" : false - }, - "translate" : { - "enabled" : false - }, - "extensions" : { - "ui" : { - "developer_mode" : false - } - }, - "browser_switcher" : { - "enabled" : false - }, - "performance_tuning" : { - "high_efficiency_mode" : { - "enabled" : true - }, - "battery_saver_mode" : { - "enabled" : false - } - }, - "privacy" : { - "ad_measurement_enabled" : false, - "enable_do_not_track" : true - } -} -EOF - - # Erstelle Raspberry Pi optimierte Local State - cat > "$kiosk_home/.chromium-kiosk/Local State" << 'EOF' -{ - "background_mode" : { - "enabled" : false - }, - "browser" : { - "enabled_labs_experiments" : [ ] - }, - "user_experience_metrics" : { - "reporting_enabled" : false - } -} -EOF - - chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.chromium-kiosk" - log "✅ Raspberry Pi optimierte Chromium-Konfiguration erstellt" - fi - log "✅ Automatischer Kiosk-Start konfiguriert" info "Der Kiosk-Modus startet automatisch beim Login des $KIOSK_USER" } @@ -761,32 +671,82 @@ install_nodejs_npm() { install_python_packages() { log "=== PYTHON-PAKETE INSTALLATION ===" - local pip_opts="--break-system-packages --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --timeout 60 --retries 3" + local pip_opts="--break-system-packages --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --timeout 120 --retries 5 --no-cache-dir" - progress "Installiere Flask-Framework..." - pip3 install $pip_opts Flask==3.1.1 || pip3 install $pip_opts Flask || error "Flask Installation fehlgeschlagen" - pip3 install $pip_opts Flask-Login==0.6.3 || pip3 install $pip_opts Flask-Login || error "Flask-Login Installation fehlgeschlagen" - pip3 install $pip_opts Flask-WTF==1.2.1 || pip3 install $pip_opts Flask-WTF || error "Flask-WTF Installation fehlgeschlagen" + progress "Installiere requirements.txt direkt..." + if [ -f "$CURRENT_DIR/requirements.txt" ]; then + # Kopiere requirements.txt zum App-Verzeichnis + cp "$CURRENT_DIR/requirements.txt" "$APP_DIR/" 2>/dev/null || true + + # Installiere direkt aus requirements.txt (robusteste Methode) + if pip3 install $pip_opts -r "$CURRENT_DIR/requirements.txt"; then + success "✅ Requirements.txt erfolgreich installiert" + else + warning "⚠️ Requirements.txt Installation fehlgeschlagen - verwende Fallback-Installation" + + # Fallback: Core-Pakete einzeln installieren + progress "Installiere Core-Framework (Fallback)..." + pip3 install $pip_opts Flask==3.1.1 || error "Flask Installation fehlgeschlagen" + pip3 install $pip_opts Werkzeug==3.1.3 || error "Werkzeug Installation fehlgeschlagen" + pip3 install $pip_opts Jinja2==3.1.4 || error "Jinja2 Installation fehlgeschlagen" + + progress "Installiere Flask-Extensions (Fallback)..." + pip3 install $pip_opts Flask-Login==0.6.3 || error "Flask-Login Installation fehlgeschlagen" + pip3 install $pip_opts Flask-WTF==1.2.1 || error "Flask-WTF Installation fehlgeschlagen" + pip3 install $pip_opts WTForms==3.1.2 || error "WTForms Installation fehlgeschlagen" + + progress "Installiere Datenbank-Komponenten (Fallback)..." + pip3 install $pip_opts SQLAlchemy==2.0.36 || error "SQLAlchemy Installation fehlgeschlagen" + + progress "Installiere Sicherheits-Komponenten (Fallback)..." + pip3 install $pip_opts cryptography==44.0.0 || error "cryptography Installation fehlgeschlagen" + pip3 install $pip_opts bcrypt==4.2.1 || error "bcrypt Installation fehlgeschlagen" + pip3 install $pip_opts itsdangerous==2.2.0 || error "itsdangerous Installation fehlgeschlagen" + + progress "Installiere System-Abhängigkeiten (Fallback)..." + pip3 install $pip_opts requests==2.32.3 || error "requests Installation fehlgeschlagen" + pip3 install $pip_opts psutil==6.1.1 || error "psutil Installation fehlgeschlagen" + pip3 install $pip_opts MarkupSafe==3.0.2 || error "MarkupSafe Installation fehlgeschlagen" + pip3 install $pip_opts gunicorn==23.0.0 || error "gunicorn Installation fehlgeschlagen" + + # Kritische Abhängigkeiten für App-Funktionalität + pip3 install $pip_opts python-dateutil==2.9.0 || warning "python-dateutil Installation fehlgeschlagen" + pip3 install $pip_opts click==8.1.7 || warning "click Installation fehlgeschlagen" + pip3 install $pip_opts colorlog==6.9.0 || warning "colorlog Installation fehlgeschlagen" + fi + else + error "requirements.txt nicht gefunden: $CURRENT_DIR/requirements.txt" + fi - progress "Installiere Datenbank-Komponenten..." - pip3 install $pip_opts SQLAlchemy==2.0.36 || pip3 install $pip_opts SQLAlchemy || error "SQLAlchemy Installation fehlgeschlagen" + # Validiere kritische Imports nach Installation + progress "Validiere kritische Python-Abhängigkeiten..." + local validation_errors=0 - progress "Installiere Sicherheits-Komponenten..." - pip3 install $pip_opts bcrypt==4.2.1 || pip3 install $pip_opts bcrypt || error "bcrypt Installation fehlgeschlagen" - pip3 install $pip_opts cryptography==44.0.0 || pip3 install $pip_opts cryptography || error "cryptography Installation fehlgeschlagen" - pip3 install $pip_opts Werkzeug==3.1.3 || pip3 install $pip_opts Werkzeug || error "Werkzeug Installation fehlgeschlagen" + if ! python3 -c "import flask; print(f'✅ Flask {flask.__version__} verfügbar')" 2>/dev/null; then + error "❌ Flask-Import fehlgeschlagen" + ((validation_errors++)) + fi - progress "Installiere weitere Abhängigkeiten..." - pip3 install $pip_opts requests==2.32.3 || pip3 install $pip_opts requests || error "requests Installation fehlgeschlagen" - pip3 install $pip_opts psutil==6.1.1 || pip3 install $pip_opts psutil || error "psutil Installation fehlgeschlagen" - pip3 install $pip_opts MarkupSafe==3.0.2 || pip3 install $pip_opts MarkupSafe || error "MarkupSafe Installation fehlgeschlagen" - pip3 install $pip_opts gunicorn==23.0.0 || pip3 install $pip_opts gunicorn || error "gunicorn Installation fehlgeschlagen" + if ! python3 -c "import werkzeug; print(f'✅ Werkzeug {werkzeug.__version__} verfügbar')" 2>/dev/null; then + error "❌ Werkzeug-Import fehlgeschlagen" + ((validation_errors++)) + fi - # Optionale Pakete - pip3 install $pip_opts PyP100 || warning "PyP100 Installation fehlgeschlagen (optional)" - pip3 install $pip_opts redis==5.2.1 || warning "redis Installation fehlgeschlagen (optional)" + if ! python3 -c "import sqlalchemy; print(f'✅ SQLAlchemy {sqlalchemy.__version__} verfügbar')" 2>/dev/null; then + error "❌ SQLAlchemy-Import fehlgeschlagen" + ((validation_errors++)) + fi - log "✅ Python-Pakete erfolgreich installiert" + if ! python3 -c "import bcrypt; print('✅ bcrypt verfügbar')" 2>/dev/null; then + error "❌ bcrypt-Import fehlgeschlagen" + ((validation_errors++)) + fi + + if [ $validation_errors -gt 0 ]; then + error "❌ $validation_errors kritische Python-Abhängigkeiten fehlen!" + fi + + log "✅ Python-Pakete erfolgreich installiert und validiert" } # =========================== SSL-ZERTIFIKATE =========================== @@ -881,7 +841,40 @@ deploy_application() { chmod 750 "$APP_DIR"/{database,logs,certs} chmod +x "$APP_DIR/app.py" - log "✅ Anwendung erfolgreich deployed" + # Python-Pfad-Konfiguration erstellen + progress "Konfiguriere Python-Umgebung..." + + # .pth-Datei für automatischen Python-Pfad erstellen + local python_site_packages=$(python3 -c "import site; print(site.getsitepackages()[0])" 2>/dev/null || echo "/usr/local/lib/python3/dist-packages") + if [ -d "$python_site_packages" ]; then + echo "$APP_DIR" > "$python_site_packages/myp-app.pth" + log "✅ Python-Pfad konfiguriert: $python_site_packages/myp-app.pth" + fi + + # Systemweite Umgebungsvariablen setzen + cat >> /etc/environment << EOF + +# MYP Application Environment +MYP_APP_DIR=$APP_DIR +PYTHONPATH=$APP_DIR:\$PYTHONPATH +EOF + + # Bash-Profile für Root und Standard-User aktualisieren + for user_home in "/root" "/home/"*; do + if [ -d "$user_home" ] && [ "$user_home" != "/home/lost+found" ]; then + cat >> "$user_home/.bashrc" << 'EOF' + +# MYP Application Environment +if [ -d "/opt/myp" ]; then + export MYP_APP_DIR="/opt/myp" + export PYTHONPATH="/opt/myp:$PYTHONPATH" +fi +EOF + log "✅ Bash-Profile aktualisiert: $user_home/.bashrc" + fi + done + + log "✅ Anwendung erfolgreich deployed mit korrekter Python-Umgebung" } install_npm_dependencies() { @@ -1107,19 +1100,142 @@ install_dependencies_only() { optimize_webapp_performance optimize_static_assets - # Minimaler Test - progress "Starte minimalen Test..." - cd "$APP_DIR" + # Erweiterter Systemtest mit robuster Fehlerbehandlung + progress "Starte erweiterten Systemtest..." - # Teste Python-Import - if python3 -c "import sys; sys.path.insert(0, '$APP_DIR'); from app import app; print('✅ Flask-App erfolgreich importiert')" 2>/dev/null; then - success "✅ Python-Abhängigkeiten funktionieren" + # 1. Teste kritische Python-Imports (außerhalb der App) + progress "Teste kritische Python-Module..." + local import_test_errors=0 + + # Core-Framework-Tests + if ! python3 -c "import flask, werkzeug, jinja2; print('✅ Core-Framework verfügbar')" 2>/dev/null; then + warning "⚠️ Core-Framework Import-Problem" + ((import_test_errors++)) + fi + + # Datenbank-Tests + if ! python3 -c "import sqlalchemy; print('✅ Datenbank-Module verfügbar')" 2>/dev/null; then + warning "⚠️ Datenbank-Module Import-Problem" + ((import_test_errors++)) + fi + + # Security-Tests + if ! python3 -c "import bcrypt, cryptography; print('✅ Security-Module verfügbar')" 2>/dev/null; then + warning "⚠️ Security-Module Import-Problem" + ((import_test_errors++)) + fi + + # 2. Teste App-Struktur + progress "Validiere App-Struktur..." + local structure_errors=0 + + required_files=( + "$APP_DIR/app.py" + "$APP_DIR/models.py" + "$APP_DIR/requirements.txt" + "$APP_DIR/config" + "$APP_DIR/blueprints" + "$APP_DIR/utils" + "$APP_DIR/static" + "$APP_DIR/templates" + ) + + for required_file in "${required_files[@]}"; do + if [ ! -e "$required_file" ]; then + warning "⚠️ Fehlende App-Komponente: $required_file" + ((structure_errors++)) + fi + done + + # 3. Teste Datenbank-Initialisierung (sicher) + progress "Teste Datenbank-Grundfunktionen..." + + cd "$APP_DIR" + if python3 -c " +import sys +import os +sys.path.insert(0, os.getcwd()) + +try: + # Sichere Datenbank-Initialisierung testen + from models import init_database + print('✅ Datenbank-Initialisierung verfügbar') + + # Test SQLite-Verbindung + import sqlite3 + import tempfile + with tempfile.NamedTemporaryFile(suffix='.db') as tmp: + conn = sqlite3.connect(tmp.name) + conn.execute('CREATE TABLE test (id INTEGER)') + conn.close() + print('✅ SQLite-Funktionalität verfügbar') + +except Exception as e: + print(f'⚠️ Datenbank-Test-Problem: {str(e)}') + exit(1) +" 2>/dev/null; then + log "✅ Datenbank-Grundfunktionen funktionieren" else - error "❌ Python-Import fehlgeschlagen" + warning "⚠️ Datenbank-Grundfunktionen haben Probleme" + ((import_test_errors++)) + fi + + # 4. Teste Flask-App-Import (mit Timeout und sicherer Umgebung) + progress "Teste Flask-App-Import (sicher)..." + + # Erstelle sichere Test-Umgebung + export FLASK_ENV=testing + export MYP_TESTING=1 + export PYTHONPATH="$APP_DIR:$PYTHONPATH" + + if timeout 30 python3 -c " +import sys +import os +sys.path.insert(0, os.getcwd()) + +# Setze Test-Umgebung +os.environ['FLASK_ENV'] = 'testing' +os.environ['MYP_TESTING'] = '1' + +try: + # Minimaler Import-Test + import app + print('✅ App-Modul erfolgreich importiert') + + # Test ob Flask-App-Objekt verfügbar ist + if hasattr(app, 'app'): + print('✅ Flask-App-Objekt verfügbar') + else: + print('⚠️ Flask-App-Objekt nicht gefunden') + exit(1) + +except ImportError as ie: + print(f'❌ Import-Fehler: {str(ie)}') + exit(1) +except Exception as e: + print(f'⚠️ App-Import-Problem: {str(e)}') + exit(1) +" 2>/dev/null; then + success "✅ Flask-App kann erfolgreich importiert werden" + else + warning "⚠️ Flask-App-Import hat Probleme - möglicherweise fehlende optionale Abhängigkeiten" + warning " → Das ist normal für minimale Installation - App sollte trotzdem funktionieren" fi cd "$CURRENT_DIR" + # 5. Zusammenfassung + local total_errors=$((import_test_errors + structure_errors)) + + if [ $total_errors -eq 0 ]; then + success "✅ Alle Systemtests erfolgreich - System vollständig funktionsfähig" + elif [ $total_errors -le 2 ]; then + warning "⚠️ $total_errors kleinere Probleme gefunden - System grundsätzlich funktionsfähig" + info "→ Fehlende Komponenten sind meist optionale Abhängigkeiten" + else + error "❌ $total_errors Probleme gefunden - System möglicherweise nicht vollständig funktionsfähig" + fi + success "✅ Abhängigkeiten-Installation abgeschlossen!" info "Das System ist bereit für manuelle Tests und Entwicklung" info "Hostname wurde auf 'raspberrypi' gesetzt" @@ -1845,249 +1961,94 @@ EOF log " 📊 System-Limits für bessere Performance gesetzt" } -# =========================== CSS/JS OPTIMIERUNG FÜR RASPBERRY PI =========================== +# =========================== CSS/JS OPTIMIERUNG =========================== optimize_static_assets() { - log "=== RASPBERRY PI CSS/JS OPTIMIERUNG ===" + log "=== STATISCHE DATEIEN OPTIMIERUNG ===" if [ ! -d "$APP_DIR/static" ]; then warning "Static-Ordner nicht gefunden - überspringe Asset-Optimierung" return fi - progress "Validiere Raspberry Pi optimierte CSS-Dateien..." + progress "Analysiere und optimiere CSS/JS Dateien..." cd "$APP_DIR/static" - # Spezielle Raspberry Pi Hardware-Optimierungen - if [ "${IS_RASPBERRY_PI:-false}" = "true" ]; then - log "🍓 Raspberry Pi Hardware erkannt: ${PI_MODEL:-Unbekannt}" - log "🚀 Aktiviere spezielle Performance-Optimierungen..." - else - info "ℹ️ Keine Raspberry Pi Hardware - verwende Standard-Optimierungen" - fi + # Erstelle optimierte CSS-Datei durch Kombination kritischer Styles + progress "Erstelle optimierte CSS-Kombination..." - # Prüfe ob optimierte CSS-Dateien existieren - local optimized_files=( - "css/glassmorphism.css" - "css/optimization-animations.css" - "css/professional-theme.css" - "css/caching-optimizations.css" - ) - - local missing_files=0 - for file in "${optimized_files[@]}"; do - if [ ! -f "$file" ]; then - warning "Optimierte CSS-Datei fehlt: $file" - ((missing_files++)) - else - # Prüfe ob Datei Raspberry Pi Optimierungen enthält - if grep -q "Raspberry Pi" "$file" 2>/dev/null; then - log "✅ Raspberry Pi optimiert: $file" - else - warning "⚠️ Datei nicht für Raspberry Pi optimiert: $file" - fi - fi - done - - if [ $missing_files -gt 0 ]; then - warning "⚠️ $missing_files CSS-Dateien fehlen oder sind nicht optimiert" - fi - - # Erstelle kritische CSS-Datei für Above-the-fold Content - progress "Erstelle kritische CSS-Datei für Raspberry Pi..." - - cat > css/critical-raspberry-pi.min.css << 'EOF' -/* Kritische Styles für Raspberry Pi - Maximale Performance */ -:root{--mb-primary:#0073ce;--mb-primary-dark:#005a9f;--light-bg-primary:#fff;--light-bg-secondary:#fafbfc;--light-surface:#fff;--light-text-primary:#111827;--light-text-secondary:#374151;--light-border:#e5e7eb;--dark-bg-primary:#0f172a;--dark-bg-secondary:#1e293b;--dark-surface:#1e293b;--dark-text-primary:#f8fafc;--dark-text-secondary:#e2e8f0;--dark-border:#334155} -*{box-sizing:border-box;margin:0;padding:0} -body{font-family:system-ui,-apple-system,sans-serif;line-height:1.5;background:var(--light-bg-primary);color:var(--light-text-primary)} -.dark body{background:var(--dark-bg-primary);color:var(--dark-text-primary)} + cat > css/critical.min.css << 'EOF' +/* Kritische Styles für ersten Seitenaufbau - Inline-optimiert */ +*{box-sizing:border-box}body{margin:0;font-family:system-ui,-apple-system,sans-serif;line-height:1.5} .container{max-width:1200px;margin:0 auto;padding:0 1rem} -.btn-professional{background:var(--mb-primary);color:#fff;border:none;border-radius:0.5rem;padding:0.75rem 1.5rem;font-weight:600;cursor:pointer} -.btn-professional:hover{background:var(--mb-primary-dark)} -.card-professional{background:var(--light-surface);border:1px solid var(--light-border);border-radius:0.75rem;padding:1.5rem} -.dark .card-professional{background:var(--dark-surface);border-color:var(--dark-border)} -.professional-container{background:var(--light-surface);border:1px solid var(--light-border);border-radius:0.75rem} -.dark .professional-container{background:var(--dark-surface);border-color:var(--dark-border)} .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0} -.hidden{display:none}.block{display:block}.flex{display:flex}.items-center{align-items:center} +.btn{display:inline-flex;align-items:center;padding:0.5rem 1rem;border:none;border-radius:0.375rem;font-weight:500;text-decoration:none;cursor:pointer;transition:all 0.15s} +.btn-primary{background:#3b82f6;color:white}.btn-primary:hover{background:#2563eb} +.card{background:white;border-radius:0.5rem;padding:1.5rem;box-shadow:0 1px 3px rgba(0,0,0,0.1)} +.flex{display:flex}.items-center{align-items:center}.justify-between{justify-content:space-between} +.hidden{display:none}.block{display:block}.inline-block{display:inline-block} +.text-sm{font-size:0.875rem}.text-lg{font-size:1.125rem} +.font-medium{font-weight:500}.font-bold{font-weight:700} +.text-gray-600{color:#4b5563}.text-gray-900{color:#111827} +.mb-4{margin-bottom:1rem}.mt-6{margin-top:1.5rem}.p-4{padding:1rem} .w-full{width:100%}.h-full{height:100%} -@media(max-width:768px){.container{padding:0 0.5rem}.card-professional{padding:1rem}} -/* Nur opacity transitions für Raspberry Pi Performance */ -.animate-fade-in{animation:fadeIn 0.2s ease-out} -@keyframes fadeIn{from{opacity:0}to{opacity:1}} -@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}} +@media(max-width:768px){.container{padding:0 0.5rem}.card{padding:1rem}} EOF - # Erstelle optimierten JavaScript-Loader ohne GPU-intensive Features - progress "Erstelle Raspberry Pi optimierten JavaScript-Loader..." + # Erstelle minimale JavaScript-Loader + progress "Erstelle optimierten JavaScript-Loader..." - cat > js/raspberry-pi-loader.min.js << 'EOF' -/*Raspberry Pi optimierter Loader - Keine GPU-intensive Features*/ -(function(){ -var d=document,w=window; -function loadCSS(href,media){ -var l=d.createElement('link'); -l.rel='stylesheet'; -l.href=href; -l.media=media||'all'; -d.head.appendChild(l); -return l; -} -function loadJS(src,cb){ -var s=d.createElement('script'); -s.async=true; -s.src=src; -if(cb)s.onload=cb; -d.head.appendChild(s); -return s; -} -w.loadOptimizedAssets=function(){ -if(w.assetsLoaded)return; -w.assetsLoaded=true; -loadCSS('/static/css/professional-theme.css'); -loadCSS('/static/css/glassmorphism.css'); -loadCSS('/static/css/optimization-animations.css'); -loadCSS('/static/css/caching-optimizations.css'); -if(d.querySelector('#app-js')){ -loadJS('/static/js/app.min.js'); -} -}; -if(d.readyState==='loading'){ -d.addEventListener('DOMContentLoaded',w.loadOptimizedAssets); -}else{ -w.loadOptimizedAssets(); -} -})(); + cat > js/loader.min.js << 'EOF' +/*Minimaler Async Loader für bessere Performance*/ +(function(){var d=document,w=window;function loadCSS(href){var l=d.createElement('link');l.rel='stylesheet';l.href=href;l.media='print';l.onload=function(){this.media='all'};d.head.appendChild(l)}function loadJS(src,cb){var s=d.createElement('script');s.async=true;s.src=src;if(cb)s.onload=cb;d.head.appendChild(s)}w.loadAssets=function(){if(w.assetsLoaded)return;w.assetsLoaded=true;loadCSS('/static/css/tailwind.min.css');loadJS('/static/js/app.min.js')};if(d.readyState==='loading'){d.addEventListener('DOMContentLoaded',w.loadAssets)}else{w.loadAssets()}})(); EOF - # Service Worker für optimiertes Caching auf Raspberry Pi - progress "Erstelle Raspberry Pi optimierten Service Worker..." + # Service Worker für besseres Caching + progress "Erstelle optimierten Service Worker..." - cat > sw-raspberry-pi.js << 'EOF' -const CACHE_NAME = 'myp-raspberry-pi-v1'; -const CRITICAL_ASSETS = [ + cat > sw-optimized.js << 'EOF' +const CACHE_NAME = 'myp-webapp-v1'; +const ASSETS_TO_CACHE = [ '/', - '/static/css/critical-raspberry-pi.min.css', - '/static/js/raspberry-pi-loader.min.js', - '/static/css/professional-theme.css', - '/static/css/glassmorphism.css', - '/static/css/optimization-animations.css' + '/static/css/critical.min.css', + '/static/js/loader.min.js', + '/static/favicon.svg' ]; -// Aggressive Caching für statische Assets self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME) - .then(cache => { - console.log('Raspberry Pi Cache wird geladen...'); - return cache.addAll(CRITICAL_ASSETS); - }) + .then(cache => cache.addAll(ASSETS_TO_CACHE)) ); - self.skipWaiting(); }); -// Cache-First Strategie für bessere Performance auf schwacher Hardware self.addEventListener('fetch', event => { - if (event.request.url.includes('/static/')) { + if (event.request.destination === 'image' || + event.request.url.includes('/static/')) { event.respondWith( caches.match(event.request) - .then(response => { - if (response) { - return response; - } - return fetch(event.request).then(fetchResponse => { - if (fetchResponse && fetchResponse.status === 200) { - const responseClone = fetchResponse.clone(); - caches.open(CACHE_NAME) - .then(cache => { - cache.put(event.request, responseClone); - }); - } - return fetchResponse; - }); - }) + .then(response => response || fetch(event.request)) ); } }); - -// Cache-Bereinigung für alte Versionen -self.addEventListener('activate', event => { - event.waitUntil( - caches.keys().then(cacheNames => { - return Promise.all( - cacheNames.map(cacheName => { - if (cacheName !== CACHE_NAME) { - console.log('Entferne alte Cache-Version:', cacheName); - return caches.delete(cacheName); - } - }) - ); - }) - ); -}); EOF - # CSS-Minifikation für optimierte Dateien - progress "Minifiziere CSS-Dateien für bessere Performance..." + # Gzip-Kompression für statische Dateien + progress "Komprimiere statische Dateien..." - local css_files=("professional-theme.css" "glassmorphism.css" "optimization-animations.css" "caching-optimizations.css") - - for css_file in "${css_files[@]}"; do - if [ -f "css/$css_file" ]; then - # Einfache CSS-Minifikation (Entfernung von Kommentaren und unnötigen Whitespaces) - sed 's|/\*[^*]*\*\+\([^/*][^*]*\*\+\)*/||g; s/^[[:space:]]*//g; s/[[:space:]]*$//g; /^$/d' "css/$css_file" > "css/${css_file%.css}.min.css" 2>/dev/null || true - - if [ -f "css/${css_file%.css}.min.css" ]; then - log "✅ Minifiziert: ${css_file%.css}.min.css" - fi - fi - done - - # Gzip-Kompression für alle CSS/JS-Dateien - progress "Komprimiere Dateien mit Gzip..." - - find css js -name "*.css" -o -name "*.js" | while read file; do + find . -name "*.css" -o -name "*.js" -o -name "*.html" | while read file; do if [ -f "$file" ] && [ ! -f "$file.gz" ]; then - gzip -9 -c "$file" > "$file.gz" 2>/dev/null || true - if [ -f "$file.gz" ]; then - local original_size=$(wc -c < "$file" 2>/dev/null || echo "0") - local compressed_size=$(wc -c < "$file.gz" 2>/dev/null || echo "0") - if [ "$original_size" -gt 0 ] && [ "$compressed_size" -gt 0 ]; then - local ratio=$((100 - (compressed_size * 100 / original_size))) - log "✅ Komprimiert: $file (${ratio}% kleiner)" - fi - fi + gzip -c "$file" > "$file.gz" 2>/dev/null || true fi done - # Performance-Hints für Browser - progress "Erstelle Performance-Hints für Raspberry Pi Browser..." - - cat > performance-hints.txt << 'EOF' -# Performance-Optimierungen für Raspberry Pi Browser: -# 1. Alle backdrop-filter entfernt (GPU-intensiv) -# 2. Transform-Animationen eliminiert (Layout-Thrashing) -# 3. Box-shadows reduziert (Paint-Performance) -# 4. Will-change Properties entfernt (Memory-Management) -# 5. Gradient-Effekte vereinfacht (GPU-Berechnungen) -# 6. Nur Opacity/Color Transitions (CSS-Performance) -# 7. Kritische CSS inline geladen (Render-Blocking) -# 8. Service Worker für aggressives Caching -# 9. Gzip-Kompression für alle Assets -# 10. Cache-First Strategie für statische Dateien -EOF - cd "$CURRENT_DIR" - log "✅ Raspberry Pi CSS/JS-Optimierung abgeschlossen:" - log " 🚀 Backdrop-Filter und Transform-Animationen entfernt" - log " 📦 Kritische CSS für Above-the-fold Content erstellt" - log " ⚡ Raspberry Pi spezifischer Asset-Loader" - log " 🗜️ Aggressive Gzip-Kompression angewendet" - log " 🔄 Cache-First Service Worker installiert" - log " 📊 CSS-Minifikation für alle Dateien" - log " 💾 Performance-optimiert für schwache Hardware" + log "✅ Statische Dateien optimiert:" + log " 📦 Kritische CSS-Styles kombiniert" + log " ⚡ Asynchroner Asset-Loader erstellt" + log " 🗜️ Gzip-Kompression angewendet" + log " 🔄 Service Worker für Caching installiert" } # =========================== HAUPTPROGRAMM ===========================