Jump to content

Conditional loading of assets

VidPly intelligently loads only the JavaScript assets required for your specific media types, thereby improving performance by avoiding unnecessary downloads.

VidPly TYPO3 Extension Logo

How it works

The DataProcessor analyses media elements and sets markers to indicate which assets are required:

MarkerLoadingWhen
needsPrivacyLayerPrivacyLayer.js + privacy-layer.cssYouTube, Vimeo or SoundCloud available
needsVidPlayVidPly core (vidply/vidply.esm.min.js + code-split blocks; compiled from TypeScript, contains the buffer indicator, the optional download button and the SoundCloud renderer)Video or audio media (no external services)
needsPlaylistPlaylistInit.js2 or more media elements OR native player
needsHLShls.js 1.6.16 (hls.min.js)HLS source (.m3u8) detected in media files
needsDASHdash.js 5.2.0 (dash.all.min.js, modern UMD)DASH source (.mpd) detected in media files

CSS is always loadedvidply.min.css is resource-efficient and is always included to ensure consistent styling. It also contains the styles for the centred buffer indicator (.vidply-loading / .vidply-buffering) and for the download button.

SoundCloud uses the ‘Privacy Layer’ path by default — In mpc-vidply SoundCloud media elements only PrivacyLayer.js + privacy-layer.css (not the VidPly core), as the SoundCloud widget iframe provides its own user interface. The bundled standalone module SoundCloudRenderer is included in the VidPly core package and is therefore only fetched for pages that already require the VidPly core for other reasons (local video/audio files, HLS, DASH). See PrivacyLayer.md → ‘Switch SoundCloud to Renderer Mode’ for activation.

Examples

Single YouTube/Vimeo/SoundCloud element

Loaded:

  • vidply.min.css (styling, including styles for the loading indicator and download button)
  • privacy-layer.css (styles for the privacy layer)
  • PrivacyLayer.js (consent handling; embeds the service iframe once consent has been given)

Not loaded:

  • VidPly player core (and therefore also not the included SoundCloudRenderer – see “PrivacyLayer.md” for enabling renderer mode)
  • PlaylistInit.js
  • hls.js
  • dash.js

Single local MP4 video

Loaded:

  • vidply.min.css
  • VidPly player (vidply/vidply.esm.min.js + chunks)
  • PlaylistInit.js (player initialisation)

Not loaded:

  • PrivacyLayer.js
  • hls.js

Video with HLS source

Loaded:

  • vidply.min.css
  • VidPly player
  • PlaylistInit.js
  • hls.js (adaptive streaming)

Not loaded:

  • PrivacyLayer.js
  • dash.js

Video with DASH source

Loaded:

  • vidply.min.css
  • VidPly player
  • PlaylistInit.js
  • dash.js (MPEG-DASH streaming)

Not loaded:

  • PrivacyLayer.js
  • hls.js

Playlist with 3 MP4 videos

Loaded:

  • vidply.min.css
  • VidPly player
  • PlaylistInit.js (playlist + player)

Not loaded:

  • PrivacyLayer.js
  • hls.js

Mixed playlist (YouTube + Vimeo + SoundCloud)

Loaded:

  • vidply.min.css
  • privacy-layer.css
  • PrivacyLayer.js
  • PlaylistInit.js (for managing the playlist)

Not loaded:

  • VidPly player (external services use native iframes via the privacy layer)
  • hls.js
  • dash.js

Mixed playlist (local MP4 files + YouTube)

Loaded:

  • vidply.min.css
  • privacy-layer.css
  • PrivacyLayer.js (for the YouTube element)
  • VidPly core (for the MP4 element – also includes the buffer indicator, the download button and the SoundCloud renderer, even if not all of these are used)
  • PlaylistInit.js

Impact on performance

Before optimisation:

  • All JavaScript files are loaded on every page using VidPly
  • Total: ~530 KB (including the embedded file ‘hls.js 1.6.16’)

After optimisation:

  • Single YouTube/Vimeo/SoundCloud video: ~7 KB (PrivacyLayer.js + privacy-layer.css)
  • Single local video: ~180 KB (VidPly core + PlaylistInit) – already includes the buffer spinner, the optional download button and the SoundCloud renderer
  • Video with HLS source: ~240 KB (VidPly + PlaylistInit + hls.js)
  • Video with DASH source: ~380 KB (VidPly + PlaylistInit + dash.js)
  • Video with HLS and DASH sources: ~440 KB (VidPly + PlaylistInit + hls.js + dash.js)

Savings:

  • External services: 97% reduction (~350 KB → ~7 KB)
  • Local video without streaming: ~65% reduction compared to the non-optimised ‘load all’ baseline
 

The size figures refer to minimised, uncompressed files. The actual transfer size after gzip/brotli compression is usually 30–40% of these values.

 

Implementation

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;
    }
}
 

Template (VidPly.html)

 
<f:render partial="VidPly/Assets" arguments="{
    needsPrivacyLayer: vidply.needsPrivacyLayer,
    needsVidPlay: vidply.needsVidPlay,
    needsPlaylist: vidply.needsPlaylist,
    needsHLS: vidply.needsHLS,
    needsDASH: vidply.needsDASH
}" />
 

Assets partial (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 1.6.16 - only for HLS streams -->
<f:if condition="{needsHLS}">
    <f:asset.script identifier="vidPlyHLS" src="EXT:mpc_vidply/Resources/Public/JavaScript/hls.min.js" defer="true"/>
</f:if>

<!-- dash.js 5.2.0 (modern UMD) - only for DASH streams -->
<f:if condition="{needsDASH}">
    <f:asset.script identifier="vidPlyDASH" src="EXT:mpc_vidply/Resources/Public/JavaScript/dash.all.min.js" defer="true"/>
</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>
 

Advantages

  1. Faster page load times – particularly for videos from external services (YouTube, Vimeo)
  2. Lower bandwidth usage – users only download what they need
  3. Improved caching – unused scripts do not burden the browser cache
  4. Automatic – No configuration required; works based on media types
  5. Intelligent detection – Page-specific optimisation based on the actual content

Browser compatibility

All major browsers support the conditional loading of assets via the TYPO3 Asset API:

  • Chrome/Edge 90+
  • Firefox 88+
  • Safari 14+
  • Mobile browsers

Test

To check conditional loading:

  1. Open your browser’s developer tools → ‘Network’ tab
  2. Create a page with a single YouTube video
  3. Reload the page and check that only ‘PrivacyLayer.js’ is loaded
  4. Create a page with a local MP4 file
  5. Reload the page and ensure that the VidPly core is loaded, but not PrivacyLayer.js

Troubleshooting

Assets are not loading:

  • Clear all TYPO3 caches
  • Check the browser console for errors
  • Check whether DataProcessor is registered

Incorrect assets are being loaded:

  • Check the media type detection in the DataProcessor
  • Check whether flags are being passed to the template
  • Clear the template cache

External services are not working:

  • Ensure that PrivacyLayer.js is loaded for YouTube/Vimeo/SoundCloud
  • Check the browser console for JavaScript errors

Future improvements

Possible future optimisations:

  • Lazy loading for CSS (currently always loaded)
  • Splitting the VidPly core into smaller modules (the SoundCloud renderer, the download button and the buffer spinner can already be loaded as separate parts via dynamic TypeScript import()– by providing function flags for the DataProcessor, we could omit these when they are not required)
  • Preloading critical assets based on the content above the fold
  • Service Worker for offline caching

Share page