Możesz na start aplikacji pokazać swoje okno ładowania. Podpinasz się w międzyczasie listenerami 'load' na wszystkie multimedia (możesz do tego celu każdemu HTMLowi nadawać customowy atrybut data-lazy-loaded). Tworzysz tablicę promisów i gdy wszystkie multimedia się załadują (czyli ich promisy się "zresolwują" a.k.a "spełnią") to ukrywasz loader (jeśli dobrze zrozumiałem, co chcesz zrobić).
const lazyLoadedElements = [...document.querySelectorAll('[data-lazy-loaded]')];
const promises = lazyLoadedElements.map( (element) => {
return new Promise( (resolve) => {
element.addEventListener( 'load', () => { resolve(element); })
} );
) );
Promise.all( promises )
.then( (response) => {
/** ukrywasz ekran ładowania */
}, (reason) => {
/** nie pobrało się, wyświetlasz jakiś komunikat, albo inaczej to obsługujesz */
} );