
So funktioniert es
Der DataProcessor analysiert Medienelemente und setzt Markierungen, die angeben, welche Assets benötigt werden:
| Markierung | Lädt | Wenn |
|---|---|---|
needsPrivacyLayer | PrivacyLayer.js + privacy-layer.css | YouTube, Vimeo oder SoundCloud vorhanden |
needsVidPlay | VidPly-Kern (vidply/vidply.esm.min.js + Code-Split-Chunks; kompiliert aus TypeScript, enthält den Puffer-Spinner, den optionalen Download-Button und den SoundCloud-Renderer) | Video- oder Audiomedien (keine externen Dienste) |
needsPlaylist | PlaylistInit.js | 2+ Medienelemente ODER nativer Player |
needsHLS | hls.js | HLS-Quelle (.m3u8) in Mediendateien erkannt |
needsDASH | dash.js | DASH-Quelle (.mpd) in Mediendateien erkannt |
CSS wird immer geladen — vidply.min.css ist schlank und wird für ein einheitliches Styling immer mitgeliefert. Es enthält auch die Stile für den zentrierten Puffer-Spinner (.vidply-loading / .vidply-buffering) und die Download-Schaltfläche.
SoundCloud verwendet standardmäßig den Privacy-Layer-Pfad — In mpc-vidply SoundCloud-Medienelemente werden nur PrivacyLayer.js + privacy-layer.css (nicht der VidPly-Kern), da der SoundCloud-Widget-iframe seine eigene Benutzeroberfläche mitbringt. Das gebündelte Standalone-Modul SoundCloudRenderer wird im VidPly-Kernpaket mitgeliefert und daher nur für Seiten abgerufen, die den VidPly-Kern bereits aus anderen Gründen benötigen (lokale Video-/Audiodateien, HLS, DASH). Siehe PrivacyLayer.md → „Switch SoundCloud to Renderer Mode“ für die Aktivierung.
Beispiele
Einzelnes YouTube-/Vimeo-/SoundCloud-Element
Geladen:
- vidply.min.css (Styling, inkl. Spinner- und Download-Button-Stile)
- privacy-layer.css (Stile für die Datenschutzebene)
- PrivacyLayer.js (Einwilligungsabwicklung, bindet den Service-Iframe nach Einwilligung ein)
Nicht geladen:
- VidPly-Player-Kern (und somit auch nicht die gebündelte
SoundCloudRenderer— siehe PrivacyLayer.md für die Aktivierung des Renderer-Modus) - PlaylistInit.js
- hls.js
- dash.js
Einzelnes lokales MP4-Video
Geladen:
- vidply.min.css
- VidPly-Player (
vidply/vidply.esm.min.js+ Chunks) - PlaylistInit.js (Player-Initialisierung)
Nicht geladen:
- PrivacyLayer.js
- hls.js
Video mit HLS-Quelle
Geladen:
- vidply.min.css
- VidPly-Player
- PlaylistInit.js
- hls.js (adaptives Streaming)
Nicht geladen:
- PrivacyLayer.js
- dash.js
Video mit DASH-Quelle
Geladen:
- vidply.min.css
- VidPly-Player
- PlaylistInit.js
- dash.js (MPEG-DASH-Streaming)
Nicht geladen:
- PrivacyLayer.js
- hls.js
Playlist mit 3 MP4-Videos
Geladen:
- vidply.min.css
- VidPly-Player
- PlaylistInit.js (Wiedergabeliste + Player)
Nicht geladen:
- PrivacyLayer.js
- hls.js
Gemischte Wiedergabeliste (YouTube + Vimeo + SoundCloud)
Geladen:
- vidply.min.css
- privacy-layer.css
- PrivacyLayer.js
- PlaylistInit.js (für die Verwaltung der Wiedergabeliste)
Nicht geladen:
- VidPly-Player (externe Dienste verwenden native Iframes über die Datenschutzschicht)
- hls.js
- dash.js
Gemischte Wiedergabeliste (lokale MP4-Dateien + YouTube)
Geladen:
- vidply.min.css
- privacy-layer.css
- PrivacyLayer.js (für das YouTube-Element)
- VidPly-Kern (für das MP4-Element – enthält auch den Puffer-Spinner, den Download-Button und den SoundCloud-Renderer, auch wenn diese nicht alle verwendet werden)
- PlaylistInit.js
Auswirkungen auf die Leistung
Vor der Optimierung:
- Alle JavaScript-Dateien werden auf jeder Seite mit VidPly geladen
- Gesamt: ~530 KB (einschließlich hls.js vom CDN)
Nach der Optimierung:
- Einzelnes YouTube-/Vimeo-/SoundCloud-Video: ~7 KB (PrivacyLayer.js + privacy-layer.css)
- Einzelnes lokales Video: ~180 KB (VidPly-Kern + PlaylistInit) – enthält bereits den Puffer-Spinner, den optionalen Download-Button und den SoundCloud-Renderer
- Video mit HLS-Quelle: ~240 KB (VidPly + PlaylistInit + hls.js)
- Video mit DASH-Quelle: ~380 KB (VidPly + PlaylistInit + dash.js)
- Video mit HLS- und DASH-Quellen: ~440 KB (VidPly + PlaylistInit + hls.js + dash.js)
Einsparungen:
- Externe Dienste: 97 % Reduzierung (~350 KB → ~7 KB)
- Lokales Video ohne Streaming: ~65 % Reduzierung gegenüber der nicht optimierten „Alles laden“-Basislinie
Die Größen sind minimiert, unkomprimiert. Die tatsächliche Übertragungsgröße beträgt nach gzip/brotli in der Regel 30–40 % dieser Werte.
Implementierung
DataProcessor (VidPlyProcessor.php)
// Analyze media types
$needsPrivacyLayer = false;
$needsVidPlay = false;
$needsPlaylist = false;
$needsHLS = false;
$needsDASH = false;
// Check for external services
if (in_array($firstTrackType, ['youtube', 'vimeo', 'soundcloud'])) {
// External services use the privacy-layer iframe path.
// SoundCloud could alternatively be routed through the bundled
// `SoundCloudRenderer` (set $needsVidPlay = true) — see PrivacyLayer.md.
$needsPrivacyLayer = true;
} else {
$needsVidPlay = true; // Native VidPly player for local video/audio (incl. HLS/DASH sources)
$needsPlaylist = true;
}
// Check for HLS and DASH streams (detected by MIME type)
foreach ($tracks as $track) {
if (in_array($track['type'], ['application/x-mpegurl', 'application/vnd.apple.mpegurl'])) {
$needsHLS = true;
}
if ($track['type'] === 'application/dash+xml') {
$needsDASH = true;
}
}
Vorlage (VidPly.html)
<f:render partial="VidPly/Assets" arguments="{
needsPrivacyLayer: vidply.needsPrivacyLayer,
needsVidPlay: vidply.needsVidPlay,
needsPlaylist: vidply.needsPlaylist,
needsHLS: vidply.needsHLS,
needsDASH: vidply.needsDASH
}" />
Assets-Teilvorlage (VidPly/Assets.html)
<!-- Privacy Layer JS - only for external services -->
<f:if condition="{needsPrivacyLayer}">
<f:asset.script identifier="vidPlyPrivacy" src="..." type="module"/>
</f:if>
<!-- HLS.js - only for HLS streams -->
<f:if condition="{needsHLS}">
<f:asset.script identifier="vidPlyHLS" src="https://cdn.jsdelivr.net/..." />
</f:if>
<!-- dash.js - only for DASH streams -->
<f:if condition="{needsDASH}">
<f:asset.script identifier="vidPlyDASH" src="https://cdn.jsdelivr.net/..." />
</f:if>
<!-- VidPly Core - only for native player -->
<f:if condition="{needsVidPlay}">
<f:asset.script identifier="vidPlyWrapper" src="..." />
<f:asset.script identifier="vidPly" src="..." type="module"/>
</f:if>
<!-- Playlist Init - for playlists or player initialization -->
<f:if condition="{needsPlaylist}">
<f:asset.script identifier="playlistInit" src="..." type="module"/>
</f:if>
Vorteile
- Schnelleres Laden der Seite – insbesondere bei Videos von externen Diensten (YouTube, Vimeo)
- Geringerer Bandbreitenverbrauch – Nutzer laden nur das herunter, was sie benötigen
- Besseres Caching – Ungenutzte Skripte belasten den Browser-Cache nicht
- Automatisch – Keine Konfiguration erforderlich, funktioniert basierend auf Medientypen
- Intelligente Erkennung – Seitenspezifische Optimierung basierend auf dem tatsächlichen Inhalt
Browserkompatibilität
Alle gängigen Browser unterstützen das bedingte Laden von Assets über die TYPO3-Asset-API:
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Mobile Browser
Testen
So überprüfen Sie das bedingte Laden:
- Öffnen Sie die DevTools des Browsers → Registerkarte „Netzwerk“
- Erstellen Sie eine Seite mit einem einzelnen YouTube-Video
- Lade die Seite neu und überprüfe, ob nur PrivacyLayer.js geladen wird
- Erstellen Sie eine Seite mit einer lokalen MP4-Datei
- Laden Sie die Seite neu und stellen Sie sicher, dass VidPly Core geladen wird, PrivacyLayer.js jedoch nicht
Fehlerbehebung
Assets werden nicht geladen:
- Alle TYPO3-Caches leeren
- Browserkonsole auf Fehler überprüfen
- Überprüfen Sie, ob DataProcessor registriert ist
Falsche Assets werden geladen:
- Überprüfen Sie die Medientyp-Erkennung im DataProcessor
- Überprüfen, ob Flags an die Vorlage übergeben werden
- Leeren Sie den Vorlagen-Cache
Externe Dienste funktionieren nicht:
- Stellen Sie sicher, dass PrivacyLayer.js für YouTube/Vimeo/SoundCloud geladen wird
- Überprüfen Sie die Browserkonsole auf JavaScript-Fehler
Zukünftige Verbesserungen
Mögliche zukünftige Optimierungen:
- Lazy-Load für CSS (wird derzeit immer geladen)
- Aufteilung des VidPly-Kerns in kleinere Module (der SoundCloud-Renderer, der Download-Button und der Puffer-Spinner lassen sich bereits als separate Blöcke über dynamische TypeScript-Variablen verzögert laden
import()s – die Bereitstellung von Feature-Flags für den DataProcessor würde es uns ermöglichen, diese zu entfernen, wenn sie nicht benötigt werden) - Kritische Assets basierend auf Above-the-Fold-Inhalten vorladen
- Service Worker für Offline-Caching