fix: Update-Hinweis vergleicht gegen den laufenden Build (D45)
Der Hinweis erschien oft für genau die Fassung, die gerade geladen war. Zwei Fehler mit derselben Wurzel — die Prüfung verglich nie mit dem laufenden Stand: - Relais statt Vergleich: der abgerufene Inhalts-Hash wurde gegen den ZULETZT ABGERUFENEN gehalten (localStorage), nicht gegen den laufenden. Beim Deploy antworten CDN-Knoten unterschiedlich; jeder Wechsel schlug an, und der Schlüssel wird von allen Tabs geteilt. - Klebendes Flag: `werkbaum-update-available` entfernte nur „Jetzt laden". Nach F5 oder „Später" blieb es stehen, und der Load-Check zeigte das Banner bei jedem weiteren Laden erneut. Verglichen wird jetzt der Commit aus dem Footer-Versionslink der laufenden Seite gegen den der abgerufenen HTML (D16 spritzt ihn in beiden Deploy-Wegen ein). Kein localStorage dazwischen; beim Laden wird nichts gemeldet, die Prüfung zwei Sekunden später holt es nach. Eine spätere „aktuell"-Meldung sammelt Banner und Footer-Symbol wieder ein. Rückfall auf den Inhalts-Hash für Builds ohne Marker (Dev-Server), Vergleichsstand dort der erste Abruf der Seiten-Sitzung. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
579dfbf789
commit
f1ac57c931
@@ -2824,3 +2824,88 @@ hervor, dieser Markensatz ist also nicht schreibbar. Das Bild stimmt trotzdem
|
||||
einem Plan ohne `!!!` werden die Marken geschrieben: `- [ ] > Mittel (M)`,
|
||||
`- [ ] > Klein (S)` und `- [ ] > Teil 3 (M)`, während `(L)`, `(XL)` und der
|
||||
Knoten ohne Größe offen bleiben.
|
||||
|
||||
## D45 — Update-Prüfung vergleicht gegen den laufenden Build, nicht gegen einen gemerkten Abruf
|
||||
Gemeldet: „Oft wird der Hinweis, dass eine neue Version vorliege, oben
|
||||
angezeigt, obwohl genau die bereits geladen wurde“ — mit dem Verdacht auf eine
|
||||
Race-Condition und der Vermutung, dass es in der Vorschau-Instanz deshalb
|
||||
immer wieder auftritt. Beides trifft zu, und es sind **zwei** Fehler, die
|
||||
dieselbe Wurzel haben: Die Prüfung verglich nie mit dem Stand, der gerade
|
||||
läuft.
|
||||
|
||||
**Wurzel: ein Relais statt eines Vergleichs.** `checkForUpdates()` holte die
|
||||
Seite und verglich ihren Inhalts-Hash mit `werkbaum-html-hash` — dem Hash des
|
||||
**zuletzt abgerufenen** Stands. Über den läuft die Aussage „neu“ also
|
||||
indirekt: Sie sagt „der Server liefert etwas anderes als beim letzten Abruf“,
|
||||
nicht „der Server liefert etwas anderes als das, was du vor dir hast“. Das
|
||||
sind verschiedene Aussagen, sobald etwas zwischen Laden und Abruf dazwischen
|
||||
kommt — und genau das tut ein CDN. Der Kommentar im Code hielt schon fest,
|
||||
dass GitHub Pages je Cache-Knoten abweichende ETags liefert; dasselbe gilt
|
||||
zeitlich für den **Inhalt**: Während ein Deploy durchläuft, antworten Knoten
|
||||
unterschiedlich, aufeinanderfolgende Abrufe wechseln zwischen alt und neu. Der
|
||||
Hash im localStorage wurde dabei bei **jedem** Abruf nachgeführt, jeder Wechsel
|
||||
schlug also erneut an — auch wenn der laufende Tab längst den neuen Stand
|
||||
hatte. Dazu kommt, dass sich alle Tabs denselben Schlüssel teilen: Zwei
|
||||
geöffnete Tabs schreiben abwechselnd ihren Stand hinein und melden einander
|
||||
Updates.
|
||||
|
||||
**Zweiter Fehler, der eigentliche Dauerbrenner: das Flag blieb kleben.**
|
||||
`werkbaum-update-available` wurde bei einem Fund gesetzt und **nur** vom Knopf
|
||||
„Jetzt laden“ wieder entfernt. Wer statt dessen F5 drückte — oder „Später“, das
|
||||
lediglich das Banner-Element entfernte —, behielt das Flag; und beim Laden
|
||||
stand:
|
||||
|
||||
```js
|
||||
if(!document.hidden && localStorage.getItem('werkbaum-update-available')){
|
||||
checkAndShowUpdateNotification();
|
||||
}
|
||||
```
|
||||
|
||||
Also erschien das Banner ausgerechnet auf der Fassung, die es gerade eingespielt
|
||||
hatte, und danach bei **jedem** weiteren Laden, bis irgendwann jemand den
|
||||
richtigen Knopf traf. Nachgestellt: Flag setzen, neu laden → Banner; „Später“ →
|
||||
Flag steht weiter; neu laden → Banner. Endlos.
|
||||
|
||||
**Entscheidung: die laufende Seite ist der Vergleichsmaßstab, und sie kennt
|
||||
sich selbst.** Beide Deploy-Wege spritzen den Commit in den
|
||||
Footer-Versionslink (D16, `<a class="ver" href="…/commit/<sha>">`) — die
|
||||
laufende Seite trägt ihre Identität also im DOM, die abgerufene im HTML-Text.
|
||||
Zwei Werte, die im selben Moment vorliegen; dazwischen kein Speicher, der
|
||||
altern könnte. Damit sind alle drei Ursachen weg: kein Relais (CDN-Flattern
|
||||
meldet nichts mehr, solange der gelieferte Commit der laufende ist), keine
|
||||
Kopplung zwischen Tabs, und nichts, was ein Neuladen überdauert. Nebengewinn:
|
||||
Schon die **erste** Prüfung nach dem Laden ist aussagekräftig — der alte Weg
|
||||
konnte beim ersten Mal grundsätzlich nichts sagen, weil er erst einen
|
||||
Vergleichsstand anlegen musste.
|
||||
|
||||
**Der Zustand lebt nur noch im Speicher.** `werkbaum-update-available` und
|
||||
`werkbaum-html-hash` werden nicht mehr geschrieben (der Reset räumt sie noch
|
||||
weg, falls sie aus einer früheren Fassung herumliegen). Beim Laden wird
|
||||
grundsätzlich **nichts** gemeldet: Was der Browser gerade geholt hat, *ist* der
|
||||
aktuelle Stand, bis eine Prüfung etwas anderes zeigt — und die läuft zwei
|
||||
Sekunden später ohnehin. Damit kann die Meldung nicht mehr klemmen: Gilt sie
|
||||
noch, kommt sie sofort wieder; gilt sie nicht, bleibt sie weg. „Später“ darf
|
||||
deshalb weiterhin nur das Element entfernen.
|
||||
|
||||
**Die Meldung wird auch wieder eingesammelt.** Sagt eine spätere Prüfung
|
||||
„aktuell“, während das Banner steht, verschwinden Banner und Footer-Symbol.
|
||||
Das deckt den Rollback ab und den Fall, dass ein einzelner Abruf doch einmal
|
||||
gegen einen veralteten Knoten lief.
|
||||
|
||||
**Rückfall für Builds ohne Marker** (Dev-Server, `file://`, lokales
|
||||
`npm run preview`): dort steht im Footer der Platzhalter `…/commit/main`, also
|
||||
keine Commit-Kennung. Dann wird weiter der Inhalts-Hash verglichen — aber gegen
|
||||
den **ersten Abruf dieser Seiten-Sitzung**, der als Vergleichsstand stehen
|
||||
bleibt, statt gegen einen fortlaufend nachgeführten Wert im localStorage. Der
|
||||
Preis ist ein blindes Fenster von zwei Sekunden zwischen Laden und Erstprüfung;
|
||||
auf dem Dev-Server ist das gleichgültig, weil dort HMR arbeitet.
|
||||
|
||||
**Nachgemessen** (Dev-Server, Marker zum Prüfen von Hand eingespritzt):
|
||||
|
||||
| Fall | vorher | nachher |
|
||||
|---|---|---|
|
||||
| Altes Flag im localStorage, neu laden | Banner, bei jedem Laden erneut | kein Banner, drei Takte „✓ Alles aktuell“ |
|
||||
| Gespeicherter Hash ≠ Auslieferung, Seite unverändert | „✅ NEUE VERSION ERKANNT!“ | „✓ Alles aktuell“ |
|
||||
| Server liefert anderen Commit | — | „✅ Neuer Build 2222222“, Banner + Footer-Symbol |
|
||||
| Danach wieder derselbe Commit | Banner blieb stehen | Banner und Symbol verschwinden |
|
||||
| „Später“, dann F5 | Banner sofort wieder da | weg und bleibt weg |
|
||||
|
||||
Reference in New Issue
Block a user