feat: Sagen, wenn Oberflaeche und Server auseinanderlaufen
Ein "npm run build" allein startet den Dienst nicht neu. Die Oberflaeche ruft dann Endpunkte auf, die es serverseitig noch gar nicht gibt - und das sieht aus wie ein Fehler in der Funktion, nicht wie ein halbes Update. Genau daran ging gerade eine Stunde Fehlersuche drauf: Die Aufstellung eines Ausgaben-Anteils blieb leer, weil der Server den Endpunkt nicht kannte. Vite setzt den Commit beim Bauen ins Bundle, die Oberflaeche vergleicht ihn beim Start mit dem, den der Server unter /api/version meldet. Weichen sie ab, steht der Hinweis samt Kommando ueber jeder Seite. Kennt eine der beiden Seiten ihren Stand nicht, schweigt der Hinweis - falscher Alarm waere schlimmer als keiner. Beide Richtungen im Browser geprueft: bei verschiedenen Staenden erscheint er, bei gleichen nicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { useAuth } from "./auth";
|
import { useAuth } from "./auth";
|
||||||
import Icon from "./components/Icon";
|
import Icon from "./components/Icon";
|
||||||
import ErrorBoundary from "./components/ErrorBoundary";
|
import ErrorBoundary from "./components/ErrorBoundary";
|
||||||
|
import StandHinweis from "./components/StandHinweis";
|
||||||
import BrandMark from "./components/BrandMark";
|
import BrandMark from "./components/BrandMark";
|
||||||
import Login from "./pages/Login";
|
import Login from "./pages/Login";
|
||||||
import ChangePassword from "./pages/ChangePassword";
|
import ChangePassword from "./pages/ChangePassword";
|
||||||
@@ -114,6 +115,9 @@ function Protected({ children, adminOnly = false, wide = false }) {
|
|||||||
<Sidebar />
|
<Sidebar />
|
||||||
<div className="main">
|
<div className="main">
|
||||||
<div className={wide ? "content content--wide" : "content"}>
|
<div className={wide ? "content content--wide" : "content"}>
|
||||||
|
{/* Halbes Update: gebaut, aber nicht neu gestartet. Ohne den Hinweis
|
||||||
|
sieht das aus wie ein Fehler in der Funktion. */}
|
||||||
|
<StandHinweis />
|
||||||
<ErrorBoundary key={pathname} bereich="Diese Seite">
|
<ErrorBoundary key={pathname} bereich="Diese Seite">
|
||||||
{children}
|
{children}
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { api } from "../api";
|
||||||
|
import Icon from "./Icon";
|
||||||
|
|
||||||
|
// Wird von Vite beim Bauen eingesetzt (siehe vite.config.js).
|
||||||
|
const GEBAUT = typeof __APP_SHA__ === "string" ? __APP_SHA__ : "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Weist darauf hin, wenn Oberfläche und Server aus verschiedenen Ständen
|
||||||
|
* stammen.
|
||||||
|
*
|
||||||
|
* Das passiert genau dann, wenn `npm run build` lief, der Dienst aber nicht neu
|
||||||
|
* gestartet wurde: Die Oberfläche ruft dann Endpunkte auf, die es serverseitig
|
||||||
|
* noch gar nicht gibt, und alles sieht nach einem Fehler in der Funktion aus
|
||||||
|
* statt nach einem halben Update.
|
||||||
|
*
|
||||||
|
* Verglichen wird nur, wenn BEIDE Seiten ihren Stand kennen – sonst schwiege
|
||||||
|
* der Hinweis besser, als falschen Alarm zu schlagen.
|
||||||
|
*/
|
||||||
|
export default function StandHinweis() {
|
||||||
|
const [server, setServer] = useState(null);
|
||||||
|
useEffect(() => {
|
||||||
|
let ok = true;
|
||||||
|
api.version().then((v) => ok && setServer(v?.git_sha || "")).catch(() => {});
|
||||||
|
return () => { ok = false; };
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!GEBAUT || !server || server === GEBAUT) return null;
|
||||||
|
return (
|
||||||
|
<div className="stand-hinweis">
|
||||||
|
<Icon name="alert" size={16} />
|
||||||
|
<span>
|
||||||
|
Oberfläche ({GEBAUT}) und Server ({server}) laufen auf verschiedenen
|
||||||
|
Ständen. Bitte <code>sudo ./deploy/update.sh</code> ausführen – sonst
|
||||||
|
fehlen dem Server Funktionen, die die Oberfläche schon aufruft.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1587,3 +1587,31 @@ tr.row-dup {
|
|||||||
flex: 0 1 auto;
|
flex: 0 1 auto;
|
||||||
max-width: 9em;
|
max-width: 9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------- Halbes Update ----------
|
||||||
|
Gebaut, aber der Dienst nicht neu gestartet: Die Oberfläche ruft dann
|
||||||
|
Endpunkte auf, die es serverseitig noch gar nicht gibt. Ohne diesen Hinweis
|
||||||
|
sieht das aus wie ein Fehler in der Funktion. */
|
||||||
|
.stand-hinweis {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: var(--sp-2);
|
||||||
|
margin-bottom: var(--sp-4);
|
||||||
|
padding: var(--sp-3) var(--sp-4);
|
||||||
|
border: 1px solid var(--warn);
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
background: var(--warn-soft);
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
line-height: 1.45;
|
||||||
|
}
|
||||||
|
.stand-hinweis svg {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
.stand-hinweis code {
|
||||||
|
padding: 1px 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: var(--surface-2);
|
||||||
|
font-size: 0.95em;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,27 @@
|
|||||||
|
import { execSync } from "node:child_process";
|
||||||
|
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import react from "@vitejs/plugin-react";
|
import react from "@vitejs/plugin-react";
|
||||||
|
|
||||||
|
// Der Commit, aus dem dieses Bundle stammt. Die Oberflaeche vergleicht ihn mit
|
||||||
|
// dem, den der Server meldet – laufen beide auseinander, wurde gebaut, aber der
|
||||||
|
// Dienst nicht neu gestartet. Das kostete schon mehrfach eine halbe Stunde
|
||||||
|
// Fehlersuche an einer Funktion, die es serverseitig noch gar nicht gab.
|
||||||
|
function commit() {
|
||||||
|
try {
|
||||||
|
return execSync("git rev-parse --short HEAD", { encoding: "utf8" }).trim();
|
||||||
|
} catch {
|
||||||
|
return ""; // Kein Git zur Hand – dann wird nichts verglichen.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Im Dev-Modus wird /api an das lokale Backend weitergeleitet. Anders als in der
|
// Im Dev-Modus wird /api an das lokale Backend weitergeleitet. Anders als in der
|
||||||
// Vorlage wird der /api-Präfix NICHT entfernt – das Backend bedient die Routen
|
// Vorlage wird der /api-Präfix NICHT entfernt – das Backend bedient die Routen
|
||||||
// bewusst unter /api/... (ein Prozess liefert API und SPA gemeinsam aus).
|
// bewusst unter /api/... (ein Prozess liefert API und SPA gemeinsam aus).
|
||||||
// In Produktion liefert derselbe FastAPI-Prozess das gebaute Frontend mit aus.
|
// In Produktion liefert derselbe FastAPI-Prozess das gebaute Frontend mit aus.
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
|
define: { __APP_SHA__: JSON.stringify(commit()) },
|
||||||
server: {
|
server: {
|
||||||
port: 5173,
|
port: 5173,
|
||||||
proxy: {
|
proxy: {
|
||||||
|
|||||||
Reference in New Issue
Block a user