Files
DogFatherGitandClaude Opus 5 8fa15c04f1 Kasse und Google-Anmeldung in der Inhaltsrichtlinie freigegeben
Fortsetzung des Musik-Fundes: PayPal und Google haetten an derselben
Stelle still versagt, sobald Dogi seine Zugangsdaten eintraegt -- leerer
Bereich statt Bezahlknopf, ohne Fehlermeldung, ohne Protokolleintrag.

Vorgehen bewusst gemessen statt geraten: Erst die Angaben der Anbieter
(PayPal "Best Practices", Google CSP-Abschnitt der Setup-Anleitung),
dann im echten Browser mit PayPals offizieller Testkennung
"client-id=test" nachgemessen und die Verstoesse ueber das Ereignis
securitypolicyviolation eingesammelt. Die Messung hat zwei Dinge
gefunden, die in keiner Anleitung standen:

- www.sandbox.paypal.com (frame-src + connect-src). Beim Einrichten
  testet man mit Sandbox-Zugangsdaten; ohne diesen Eintrag haette die
  Kasse in genau dieser Phase nicht abgeschlossen werden koennen.
- accounts.google.com/gsi/style (style-src). 'unsafe-inline' deckt das
  NICHT ab -- es erlaubt nur Stile im Dokument, keine nachgeladene
  Stilvorlage. Der Anmelde-Knopf waere unformatiert erschienen.

Bewusst einzelne Adressen statt PayPals vorgeschlagener Platzhalter
(*.paypal.com): Was die Messung nicht gebraucht hat, steht nicht drin.
Skripte bleiben ohne 'unsafe-inline' -- die Pruefsummen-Loesung fuer die
eigenen Inline-Bloecke bleibt unangetastet, und ein zusaetzliches
'unsafe-inline' waere neben Pruefsummen ohnehin wirkungslos.

Neuer Test pruef-kasse.mjs (15 Pruefungen): laedt das echte PayPal-SDK,
baut die Bezahlknoepfe wirklich auf, rendert den echten Google-Knopf und
verlangt NULL Verstoesse. Bestandstest pruef-inhaltsrichtlinie.mjs (22)
und pruef-musik.mjs (17) bleiben gruen -- inklusive der Gegenprobe, dass
eingeschleuste Skripte weiterhin blockiert werden.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-27 15:11:27 +02:00

68 lines
2.9 KiB
JavaScript

/* =====================================================================
Wie schwer und wie schnell sind die öffentlichen Seiten?
Misst je Seite die übertragene Datenmenge und die Ladezeit bis
"fertig geladen", und sammelt die größten Einzelressourcen über alle
Seiten. Ziel ist NICHT ein grüner Haken, sondern das Finden konkreter
Brocken, die sich lohnen zu verkleinern -- so wie am 27.08. das 2,5-MB-
PNG "Event des Jahres" gefunden wurde.
Gegen die echte Domain, mit leerem Cache (jeder Aufruf frische Seite).
===================================================================== */
import { chromium } from "playwright";
const BASIS = "https://dogfather-universe.com";
const SEITEN = [
"/", "/dogfather.html", "/hasidog.html", "/manager.html", "/casper.html",
"/vanvan.html", "/tt-muddi.html", "/zeitreise.html", "/streamer.html",
"/community.html", "/stimmen.html", "/streamplan.html", "/team-modis.html",
"/team-scouts.html", "/creator.html", "/werte.html", "/bewerben.html",
"/kontakt.html", "/links.html", "/supporter.html", "/abonnieren.html",
"/medien-dogfather.html", "/medien-hasidog.html", "/medien-casper.html",
];
const browser = await chromium.launch();
const groessteJeRessource = new Map(); // url -> bytes
const proSeite = [];
for (const pfad of SEITEN) {
const seite = await browser.newPage();
let bytes = 0;
seite.on("response", async (r) => {
try {
const h = r.headers();
const len = Number(h["content-length"] || 0);
let b = len;
if (!b) { try { b = (await r.body()).length; } catch { b = 0; } }
bytes += b;
const u = r.url();
if (b > (groessteJeRessource.get(u) || 0)) groessteJeRessource.set(u, b);
} catch { /* egal */ }
});
const start = Date.now();
try {
await seite.goto(BASIS + pfad, { waitUntil: "networkidle", timeout: 45000 });
} catch { /* trotzdem messen, was da war */ }
const dauer = Date.now() - start;
proSeite.push({ pfad, kb: Math.round(bytes / 1024), ms: dauer });
await seite.close();
}
await browser.close();
console.log("\n=== Pro Seite (übertragen / Ladezeit), schwerste zuerst ===");
for (const s of proSeite.sort((a, b) => b.kb - a.kb)) {
const warn = s.kb > 2000 ? " ⚠ schwer" : s.kb > 1000 ? " · mittel" : "";
console.log(` ${String(s.kb).padStart(5)} KB ${String(s.ms).padStart(5)} ms ${s.pfad}${warn}`);
}
const schnitt = Math.round(proSeite.reduce((a, s) => a + s.kb, 0) / proSeite.length);
console.log(` ---\n Schnitt: ${schnitt} KB / Seite`);
console.log("\n=== Die 12 größten Einzelressourcen (Kandidaten zum Verkleinern) ===");
const top = [...groessteJeRessource].sort((a, b) => b[1] - a[1]).slice(0, 12);
for (const [u, b] of top) {
const kb = Math.round(b / 1024);
const kurz = u.replace(BASIS, "").replace(/\?.*$/, "");
const warn = kb > 500 ? " ⚠" : "";
console.log(` ${String(kb).padStart(5)} KB ${kurz}${warn}`);
}