Adaption of dashboard to Vite and React

This commit is contained in:
2025-09-13 10:03:50 +00:00
parent 1d23b7591d
commit c5a8571e97
6 changed files with 87 additions and 114 deletions

View File

@@ -1,52 +1,25 @@
# ========================================== # ==========================================
# dashboard/Dockerfile (Production) # dashboard/Dockerfile (Production)
# 🔧 OPTIMIERT: Multi-Stage-Build für ein minimales Produktions-Image
# ========================================== # ==========================================
# Stage 1: Build-Umgebung
FROM node:20-alpine AS build FROM node:20-alpine AS build
WORKDIR /app WORKDIR /app
# Kopiere package.json und pnpm-lock.yaml # Kopiere package.json und Lockfile aus dem Build-Kontext (./dashboard)
COPY package.json package-lock.json ./ COPY package*.json ./
# Installiere pnpm und dann die Abhängigkeiten # Produktions-Abhängigkeiten installieren
# --prod stellt sicher, dass nur Produktions-Abhängigkeiten installiert werden ENV NODE_ENV=production
RUN npm install --frozen-lockfile RUN npm ci --omit=dev
# Kopiere den restlichen Quellcode # Quellcode kopieren und builden
COPY . . COPY . .
# Setze Build-Argumente als Umgebungsvariablen
ARG VITE_API_URL ARG VITE_API_URL
ENV VITE_API_URL=${VITE_API_URL} ENV VITE_API_URL=${VITE_API_URL}
# Baue die Anwendung für die Produktion
RUN npm run build RUN npm run build
# Stage 2: Produktions-Umgebung
FROM nginx:1.25-alpine FROM nginx:1.25-alpine
# Kopiere die gebauten statischen Dateien aus der Build-Stage
COPY --from=build /app/dist /usr/share/nginx/html COPY --from=build /app/dist /usr/share/nginx/html
# Optional: Eine Nginx-Konfiguration für Single-Page-Applications (SPA)
# Diese leitet alle Anfragen, die keine Dateien sind, auf die index.html um.
# Erstelle eine Datei `nginx.prod.conf` mit folgendem Inhalt:
# server {
# listen 80;
# root /usr/share/nginx/html;
# index index.html;
# location / {
# try_files $uri $uri/ /index.html;
# }
# }
# COPY nginx.prod.conf /etc/nginx/conf.d/default.conf
# Exponiere Port 80 (Standard-HTTP-Port von Nginx)
EXPOSE 80 EXPOSE 80
CMD ["nginx", " -g", "daemon off;"]
# Starte Nginx
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -4,32 +4,25 @@
# ========================================== # ==========================================
FROM node:20-alpine FROM node:20-alpine
# Setze das Arbeitsverzeichnis auf den Workspace-Root, um die Pfade aus # Stelle sicher, dass benötigte Tools verfügbar sind (z. B. für wait-for-backend.sh)
# docker-compose.override.yml korrekt aufzulösen.
WORKDIR /workspace
# 🔧 HINZUGEFÜGT: Installiere curl, damit das wait-for-backend.sh Skript funktioniert
RUN apk add --no-cache curl RUN apk add --no-cache curl
RUN npm install -g npm # Setze Arbeitsverzeichnis direkt auf das Dashboard-Verzeichnis im Container
# (Der Build-Kontext ist ./dashboard, siehe docker-compose.override.yml)
# Kopiere die package-Dateien in das korrekte Unterverzeichnis.
# Dies nutzt den Docker-Cache: Wenn sich die Dateien nicht ändern,
# wird der `npm install`-Schritt übersprungen.
COPY package.json package-lock.json* ./
# Wechsle in das Dashboard-Verzeichnis, um die Befehle auszuführen.
WORKDIR /workspace/dashboard WORKDIR /workspace/dashboard
# Installiere ALLE Abhängigkeiten (inkl. devDependencies) # KOPIEREN: Nur package-Dateien relativ zum Build-Kontext (KEINE /workspace-Pfade)
RUN npm install # package*.json deckt sowohl package.json als auch package-lock.json ab, falls vorhanden
COPY package*.json ./
# Das Kopieren des restlichen Codes ist nicht nötig, da das gesamte # Installation robust machen: npm ci erfordert package-lock.json; fallback auf npm install
# Verzeichnis `./:/workspace` in der docker-compose.override.yml gemountet wird. RUN if [ -f package-lock.json ]; then \
npm ci --legacy-peer-deps; \
else \
npm install --legacy-peer-deps; \
fi && \
npm cache clean --force
# Exponiere die Ports für Vite und Node-Debugging EXPOSE 5173 9230
EXPOSE 5173 9229
# Der Startbefehl wird in der docker-compose.override.yml definiert.
# Ein Standard-CMD ist dennoch eine gute Praxis.
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0", "--port", "5173"] CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0", "--port", "5173"]

View File

@@ -8,32 +8,33 @@
"name": "dashboard", "name": "dashboard",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@syncfusion/ej2-base": "^30.2.6", "@syncfusion/ej2-base": "^30.2.0",
"@syncfusion/ej2-buttons": "^30.2.4", "@syncfusion/ej2-buttons": "^30.2.0",
"@syncfusion/ej2-calendars": "^30.2.4", "@syncfusion/ej2-calendars": "^30.2.0",
"@syncfusion/ej2-dropdowns": "^30.2.6", "@syncfusion/ej2-dropdowns": "^30.2.0",
"@syncfusion/ej2-grids": "^30.2.6", "@syncfusion/ej2-grids": "^30.2.0",
"@syncfusion/ej2-icons": "^30.2.4", "@syncfusion/ej2-icons": "^30.2.0",
"@syncfusion/ej2-inputs": "^30.2.6", "@syncfusion/ej2-inputs": "^30.2.0",
"@syncfusion/ej2-kanban": "^30.2.4", "@syncfusion/ej2-kanban": "^30.2.0",
"@syncfusion/ej2-layouts": "^30.2.4", "@syncfusion/ej2-layouts": "^30.2.0",
"@syncfusion/ej2-lists": "^30.2.4", "@syncfusion/ej2-lists": "^30.2.0",
"@syncfusion/ej2-navigations": "^30.2.7", "@syncfusion/ej2-navigations": "^30.2.0",
"@syncfusion/ej2-notifications": "^30.2.4", "@syncfusion/ej2-notifications": "^30.2.0",
"@syncfusion/ej2-popups": "^30.2.4", "@syncfusion/ej2-popups": "^30.2.0",
"@syncfusion/ej2-react-buttons": "^30.2.4", "@syncfusion/ej2-react-base": "^30.2.0",
"@syncfusion/ej2-react-calendars": "^30.1.37", "@syncfusion/ej2-react-buttons": "^30.2.0",
"@syncfusion/ej2-react-dropdowns": "^30.1.37", "@syncfusion/ej2-react-calendars": "^30.2.0",
"@syncfusion/ej2-react-filemanager": "^30.1.38", "@syncfusion/ej2-react-dropdowns": "^30.2.0",
"@syncfusion/ej2-react-grids": "^30.1.40", "@syncfusion/ej2-react-filemanager": "^30.2.0",
"@syncfusion/ej2-react-inputs": "^30.1.38", "@syncfusion/ej2-react-grids": "^30.2.0",
"@syncfusion/ej2-react-kanban": "^30.1.37", "@syncfusion/ej2-react-inputs": "^30.2.0",
"@syncfusion/ej2-react-layouts": "^30.1.40", "@syncfusion/ej2-react-kanban": "^30.2.0",
"@syncfusion/ej2-react-navigations": "^30.2.7", "@syncfusion/ej2-react-layouts": "^30.2.0",
"@syncfusion/ej2-react-notifications": "^30.1.37", "@syncfusion/ej2-react-navigations": "^30.2.0",
"@syncfusion/ej2-react-popups": "^30.1.37", "@syncfusion/ej2-react-notifications": "^30.2.0",
"@syncfusion/ej2-react-schedule": "^30.1.37", "@syncfusion/ej2-react-popups": "^30.2.0",
"@syncfusion/ej2-splitbuttons": "^30.2.4", "@syncfusion/ej2-react-schedule": "^30.2.0",
"@syncfusion/ej2-splitbuttons": "^30.2.0",
"cldr-data": "^36.0.4", "cldr-data": "^36.0.4",
"lucide-react": "^0.522.0", "lucide-react": "^0.522.0",
"react": "^19.1.0", "react": "^19.1.0",

View File

@@ -10,32 +10,33 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@syncfusion/ej2-base": "^30.2.6", "@syncfusion/ej2-base": "^30.2.0",
"@syncfusion/ej2-buttons": "^30.2.4", "@syncfusion/ej2-buttons": "^30.2.0",
"@syncfusion/ej2-calendars": "^30.2.4", "@syncfusion/ej2-calendars": "^30.2.0",
"@syncfusion/ej2-dropdowns": "^30.2.6", "@syncfusion/ej2-dropdowns": "^30.2.0",
"@syncfusion/ej2-grids": "^30.2.6", "@syncfusion/ej2-grids": "^30.2.0",
"@syncfusion/ej2-icons": "^30.2.4", "@syncfusion/ej2-icons": "^30.2.0",
"@syncfusion/ej2-inputs": "^30.2.6", "@syncfusion/ej2-inputs": "^30.2.0",
"@syncfusion/ej2-kanban": "^30.2.4", "@syncfusion/ej2-kanban": "^30.2.0",
"@syncfusion/ej2-layouts": "^30.2.4", "@syncfusion/ej2-layouts": "^30.2.0",
"@syncfusion/ej2-lists": "^30.2.4", "@syncfusion/ej2-lists": "^30.2.0",
"@syncfusion/ej2-navigations": "^30.2.7", "@syncfusion/ej2-navigations": "^30.2.0",
"@syncfusion/ej2-notifications": "^30.2.4", "@syncfusion/ej2-notifications": "^30.2.0",
"@syncfusion/ej2-popups": "^30.2.4", "@syncfusion/ej2-popups": "^30.2.0",
"@syncfusion/ej2-react-buttons": "^30.2.4", "@syncfusion/ej2-react-base": "^30.2.0",
"@syncfusion/ej2-react-calendars": "^30.1.37", "@syncfusion/ej2-react-buttons": "^30.2.0",
"@syncfusion/ej2-react-dropdowns": "^30.1.37", "@syncfusion/ej2-react-calendars": "^30.2.0",
"@syncfusion/ej2-react-filemanager": "^30.1.38", "@syncfusion/ej2-react-dropdowns": "^30.2.0",
"@syncfusion/ej2-react-grids": "^30.1.40", "@syncfusion/ej2-react-filemanager": "^30.2.0",
"@syncfusion/ej2-react-inputs": "^30.1.38", "@syncfusion/ej2-react-grids": "^30.2.0",
"@syncfusion/ej2-react-kanban": "^30.1.37", "@syncfusion/ej2-react-inputs": "^30.2.0",
"@syncfusion/ej2-react-layouts": "^30.1.40", "@syncfusion/ej2-react-kanban": "^30.2.0",
"@syncfusion/ej2-react-navigations": "^30.2.7", "@syncfusion/ej2-react-layouts": "^30.2.0",
"@syncfusion/ej2-react-notifications": "^30.1.37", "@syncfusion/ej2-react-navigations": "^30.2.0",
"@syncfusion/ej2-react-popups": "^30.1.37", "@syncfusion/ej2-react-notifications": "^30.2.0",
"@syncfusion/ej2-react-schedule": "^30.1.37", "@syncfusion/ej2-react-popups": "^30.2.0",
"@syncfusion/ej2-splitbuttons": "^30.2.4", "@syncfusion/ej2-react-schedule": "^30.2.0",
"@syncfusion/ej2-splitbuttons": "^30.2.0",
"cldr-data": "^36.0.4", "cldr-data": "^36.0.4",
"lucide-react": "^0.522.0", "lucide-react": "^0.522.0",
"react": "^19.1.0", "react": "^19.1.0",

View File

@@ -1,16 +1,20 @@
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react'; import react from '@vitejs/plugin-react';
// import path from 'path';
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react()], plugins: [react()],
resolve: { resolve: {
alias: { // 🔧 KORRIGIERT: Entferne die problematischen Aliases komplett
'@syncfusion/ej2-react-navigations': '@syncfusion/ej2-react-navigations/index.js', // Diese verursachen das "not an absolute path" Problem
'@syncfusion/ej2-react-buttons': '@syncfusion/ej2-react-buttons/index.js', // alias: {
}, // '@syncfusion/ej2-react-navigations': '@syncfusion/ej2-react-navigations/index.js',
// '@syncfusion/ej2-react-buttons': '@syncfusion/ej2-react-buttons/index.js',
// },
}, },
optimizeDeps: { optimizeDeps: {
// 🔧 NEU: Force pre-bundling der Syncfusion Module
include: [ include: [
'@syncfusion/ej2-react-navigations', '@syncfusion/ej2-react-navigations',
'@syncfusion/ej2-react-buttons', '@syncfusion/ej2-react-buttons',
@@ -19,6 +23,7 @@ export default defineConfig({
'@syncfusion/ej2-buttons', '@syncfusion/ej2-buttons',
'@syncfusion/ej2-react-base', '@syncfusion/ej2-react-base',
], ],
// 🔧 NEU: Force dependency re-optimization
force: true, force: true,
esbuildOptions: { esbuildOptions: {
target: 'es2020', target: 'es2020',
@@ -33,6 +38,7 @@ export default defineConfig({
}, },
server: { server: {
host: '0.0.0.0', host: '0.0.0.0',
port: 5173,
watch: { watch: {
usePolling: true, usePolling: true,
}, },

View File

@@ -112,9 +112,8 @@ services:
# ✅ GEÄNDERT: Dashboard jetzt mit Node.js/React statt Python/Dash # ✅ GEÄNDERT: Dashboard jetzt mit Node.js/React statt Python/Dash
dashboard: dashboard:
build: build:
context: . context: ./dashboard
dockerfile: dashboard/Dockerfile dockerfile: Dockerfile
# 🔧 VEREINFACHT: Build-Args werden durch Umgebungsvariablen gesetzt
args: args:
- VITE_API_URL=${API_URL} - VITE_API_URL=${API_URL}
image: infoscreen-dashboard:latest image: infoscreen-dashboard:latest