Skip to content
Advertisement

Conditional import in Vue component

I have a root instance that has several CustomVideo-components in it (amongst a bunch of other components). The CustomVideo-component implements VideoJS, but it’s not on all pages that there is a CustomVideo-component, so I don’t want to import VideoJS globally. Here is an example of components on a page:

App.js
|
|-- CustomVideo
|-- FooComponent
|-- CustomVideo
|-- BarComponent
|-- CustomVideo

In the top of CustomVideo, I import VideoJS, like so:

import videojs from 'video.js';
import abLoopPlugin from 'videojs-abloop'


export default {
  name: "FeaturedVideoPlayer",
  props: {
    videoUrl: String
  }
  mounted() {
    let videoOptions = {
      sources: [
        {
          src: this.videoUrl,
          type: "video/mp4"
        }
      ],
      plugins: {
        abLoopPlugin: {
          'enabled': true
        }
      }
    };

    this.player = videojs(this.$refs.featuredVideoPlayer, videoOptions, function onPlayerReady() {});

  }

But if there are more than one CustomVideo, then I get a console warning:

VIDEOJS: WARN: A plugin named “abLoopPlugin” already exists. You may want to avoid re-registering plugins!

I tried looking into conditional imports, but it doesn’t seem like it’s the way to do it.


Even if I try and import it in app.js, even though I would rather import it CustomVideo, then I get another console error:

Attempt

import abLoopPlugin from 'videojs-abloop'
Vue.use( abLoopPlugin );

Then I get the error:

Uncaught TypeError: Cannot read property ‘registerPlugin’ of undefined


How do I ensure that a plugin is registered only once?

Advertisement

Answer

Check videojs.getPlugins().abLoopPlugin

videojs.getPlugins() returns a symbol table of all loaded plugin names. You could simply check that abLoopPlugin is not in that table before loading it in your component:

import videojs from 'video.js'

if (!videojs.getPlugins().abLoopPlugin) {
  abLoopPlugin(window, videojs)
}

Await $nextTick before using ref

You’ll notice that your videos are initially not visible in your specified <video> element. This is because the ref is undefined when you pass it to videojs in mounted().

The ref docs state:

An important note about the ref registration timing: because the refs themselves are created as a result of the render function, you cannot access them on the initial render – they don’t exist yet!

The solution is to wait until the $nextTick():

async mounted() {
  // this.$refs.featuredVideoPlayer is undefined here
  await this.$nextTick()

  // this.$refs.featuredVideoPlayer is the <video> here
  this.player = videojs(this.$refs.featuredVideoPlayer)
}

Edit Using videojs-abloop in Vue

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement