Adaption of dashboard to Vite and React
This commit is contained in:
@@ -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;"]
|
|
||||||
|
|
||||||
|
|||||||
@@ -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"]
|
||||||
|
|||||||
53
dashboard/package-lock.json
generated
53
dashboard/package-lock.json
generated
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user