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>