I having a problem optimizing the performance of my application build in Vuejs3/Vite and Aframe. I need to somehow prefetch 6 videos. The problem is that each time I open a modal the browser fetches a video again. I want the browser to only fetch it once and store it somehow.
My application should look like this. Homepage has 6 buttons. On click, each button opens a modal. Inside the modal there a 6 videos. So, when a user clicks on the 2nd button the modal opens and inside it is only the 2nd video playing automatically. When a user clicks on a “close” button the modal is closed and the video is paused.
Right now my code looks like this: HTML template
// 6 button-images like this <a-image class="link" src="/play-new.png" sound="on: click; src: #click-sound" @click="openVideo(0)" position="-5 1.5 -4.5" rotation="0 60 0" ></a-image> // Modal <div v-show="isModalOpen" class="" <div v-for="(video, i) in videos" :key="i"> <video :src="video.file" loop class="block" :class="i === currentVideo ? 'play' : 'hidden'" v-show="$nextTick(() => i === currentVideo && play(i))" /> <div class=""> <button @click="hideVideo" class="">X</button> </div> </div> </div>
My JS:
<script setup> import { ref } from 'vue' const videos = [ { file: 'videos/1.mp4', }, { file: 'videos/2.mp4' }, { file: 'videos/3.mp4' }, { file: 'videos/4.mp4' }, { file: 'videos/5.mp4' }, { file: 'videos/6.mp4' } ]; const currentVideo = ref(-1); const isModalOpen = ref(false); function openVideo(videoIndex) { currentVideo.value = videoIndex; //videos[videoIndex].file; isModalOpen.value = true; } function hideVideo() { document.querySelector('.play').pause(); currentVideo.value = -1; isModalOpen.value = false; } function play(index) { if (index == currentVideo.value) { document.querySelector('.play').play(); return true; } return false; } </script>
Here what my network tab look like after I restart the page and open a modal. The initial load is red. The modal open is green.
What I’ve tried so far:
Instead of v-if
I made it work with v-show
because with v-if it is not fetched at all.
To sum it all up, how do I make a browser only load a video once and cache/store it.
Advertisement
Answer
Wrapping your component with <keep-alive>
should work:
// Modal <div v-show="isModalOpen" class="" <div v-for="(video, i) in videos" :key="i"> <keep-alive> <video :src="video.file" loop class="block" :class="i === currentVideo ? 'play' : 'hidden'" v-if="$nextTick(() => i === currentVideo && play(i))" /> </keep-alive> <div class=""> <button @click="hideVideo" class="">X</button> </div> </div> </div>