Getrennter Titel fuer Suchergebnisse je Seite und Beitrag (Migration 20260913000100): auf der Seite steht "Leistungen", im Suchergebnis darf der lange Titel stehen. Leer heisst weiterhin: der Titel der Seite. Schriften kommen jetzt vom eigenen Server. Ein Knopf im Designbereich oder cms:fonts:fetch holt die gewaehlten Google-Schnitte als WOFF2 nach public/assets/fonts. Das spart zwei fremde Verbindungen nacheinander (gemessen 820 ms) und die IP-Weitergabe an Google. Ohne Dateien bleibt es beim bisherigen Verweis - eine Seite ohne Schrift waere schlimmer. Ein Stylesheet statt vier, mit Pruefsumme im Namen und ohne Kommentare, dazu eine .htaccess mit Kompression, Cache und Schutz interner Dateien. Der Entwicklungsserver sendet dieselben Kopfzeilen, sonst misst man lokal etwas, das es im Betrieb nicht gibt. Bilder in der Groesse, in der sie erscheinen: ein nur fuer Desktop gesetztes Hintergrundbild gilt auf dem Telefon in Telefongroesse (189 KB -> 40 KB), img nennt seine feste Breite oder sizes="auto", und fetchpriority liegt auf dem ersten Bild des Inhalts statt auf dem Logo. Neu: npm run test:links prueft jeden internen Verweis auf seine Antwort. Lighthouse gegen den Nachbau: Barrierefreiheit, Best Practices und SEO 100 auf allen vier geprueften Adressen, Performance 100 ausser auf der bilderreichen Startseite (98 mobil, 96 Desktop). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
66 lines
3.0 KiB
ApacheConf
66 lines
3.0 KiB
ApacheConf
DirectoryIndex index.php
|
|
Options -Indexes -MultiViews
|
|
|
|
# Alles, was keine Datei ist, beantwortet PHP.
|
|
RewriteEngine On
|
|
RewriteCond %{REQUEST_FILENAME} !-f
|
|
RewriteRule ^ index.php [L]
|
|
|
|
# HTTPS erzwingen. Auskommentiert, weil diese Datei auch in Installationen ohne Zertifikat
|
|
# liegt und eine Endlosschleife schlimmer waere als fehlendes HTTPS. Vor dem Livegang mit
|
|
# Zertifikat: die drei Zeilen einschalten - und erst danach die HSTS-Zeile weiter unten,
|
|
# denn HSTS laesst sich in einem Browser ein halbes Jahr lang nicht zuruecknehmen.
|
|
#RewriteCond %{HTTPS} !=on
|
|
#RewriteCond %{HTTP:X-Forwarded-Proto} !=https
|
|
#RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
|
|
|
|
# Uebertragen wird komprimiert. HTML, CSS, JavaScript und XML schrumpfen dabei auf etwa ein
|
|
# Viertel; Bilder und Schriften sind bereits komprimiert und bleiben aussen vor.
|
|
<IfModule mod_deflate.c>
|
|
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
|
|
AddOutputFilterByType DEFLATE application/javascript application/json application/xml
|
|
AddOutputFilterByType DEFLATE application/rss+xml image/svg+xml
|
|
</IfModule>
|
|
<IfModule mod_brotli.c>
|
|
AddOutputFilterByType BROTLI_COMPRESS text/html text/css application/javascript image/svg+xml
|
|
</IfModule>
|
|
|
|
# Wie lange ein Browser eine Datei behalten darf.
|
|
#
|
|
# Bilder und Schriften tragen ihre Kennung im Namen: aendert sich der Inhalt, aendert sich die
|
|
# Adresse. Sie duerfen deshalb ein Jahr bleiben. Stylesheets und Skripte tragen die Fassung als
|
|
# Parameter, also ebenfalls ein Jahr. HTML wird nie zwischengespeichert - eine veroeffentlichte
|
|
# Aenderung soll beim naechsten Aufruf sichtbar sein; die Seiten senden dafuer selbst no-store.
|
|
<IfModule mod_expires.c>
|
|
ExpiresActive On
|
|
ExpiresByType image/webp "access plus 1 year"
|
|
ExpiresByType image/png "access plus 1 year"
|
|
ExpiresByType image/jpeg "access plus 1 year"
|
|
ExpiresByType image/svg+xml "access plus 1 year"
|
|
ExpiresByType font/woff2 "access plus 1 year"
|
|
ExpiresByType text/css "access plus 1 year"
|
|
ExpiresByType application/javascript "access plus 1 year"
|
|
</IfModule>
|
|
<IfModule mod_headers.c>
|
|
<FilesMatch "\.(webp|png|jpe?g|gif|svg|woff2|css|js)$">
|
|
Header set Cache-Control "public, max-age=31536000, immutable"
|
|
</FilesMatch>
|
|
# Schriften werden von derselben Adresse geladen; die Regel steht hier, damit sie auch dann
|
|
# gilt, wenn eine Installation die Dateien ueber ein CDN spiegelt.
|
|
<FilesMatch "\.woff2$">
|
|
Header set Access-Control-Allow-Origin "*"
|
|
</FilesMatch>
|
|
# Erst einschalten, wenn HTTPS steht und bleiben soll (siehe oben).
|
|
#Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
|
</IfModule>
|
|
|
|
# Nichts ausliefern, was nur intern gebraucht wird - falls jemand das Paket versehentlich
|
|
# vollstaendig in den oeffentlichen Ordner legt statt nur public/.
|
|
<FilesMatch "^\.|\.(env|db|sqlite|lock|md|yaml|yml|dist|log)$">
|
|
Require all denied
|
|
</FilesMatch>
|
|
# Eine Ausnahme mit Grund: der Editor liest die Liste der Gestaltungswerte als JSON.
|
|
<Files "design-tokens.json">
|
|
Require all granted
|
|
</Files>
|