Skip to content

Using with simultaneously rendered components #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
rdunk opened this issue Oct 16, 2017 · 5 comments · Fixed by #29
Closed

Using with simultaneously rendered components #12

rdunk opened this issue Oct 16, 2017 · 5 comments · Fixed by #29
Labels

Comments

@rdunk
Copy link

rdunk commented Oct 16, 2017

I have a view in my app which renders multiple video player components in a v-for loop. This component uses vue-script2's promise based loading to load a remote script in the mounted() lifecycle hook.

As these components are rendered simultaneously, I notice the remote script is actually added multiple times (once for each component). I'm assuming this package doesn't perform any checks for pending scripts or anything like that? Should I be using a different method for loading these?

@taoeffect taoeffect added the bug label Oct 19, 2017
@taoeffect
Copy link
Owner

taoeffect commented Oct 19, 2017

Well, on line 54 you'll see that it avoids loading files that have already been loaded, but you're right that if you try to load the same script really quickly in a row, before any one of them has finished loading, it will (currently) load the script multiple times in a row.

However, it's highly unusual to load the same <script> tag more than once. I can't think of a time I've ever seen that done.

I have seen iframes used with media players, and maybe that iframe contains a VueScript2 component in it, but in that case there's nothing (I don't think) we could do to prevent it from being loaded multiple times.

If you're not using iframes, well, I guess I'd have to see what you're trying to do. There's probably a workaround that makes more sense.

@rdunk
Copy link
Author

rdunk commented Oct 23, 2017

In my specific use case, I'm rendering multiple inline videos in a single long form blog post. I'm avoiding this issue in 95% of circumstances now by lazy loading the reusable component that loads the script.

The only way I can think to avoid this by having some sort of central bus/store that queues scripts to be loaded, but that would have an unwanted performance impact as they'd need to be loaded in sequence.

@taoeffect
Copy link
Owner

So, I'm curious about the precise implementation that's being used. I just can't help much without knowing what you're doing.

@rdunk
Copy link
Author

rdunk commented Oct 25, 2017

I'll try and describe my use case, the code should become publicly available soon so I will provide a link when it is.

I've built a Vue component for displaying videos hosted on the Brightcove video platform. Brightcove allows you to maintain a library of custom players. You can assign each player various plugins that are stored in git repositories on the platform. Brightcove compiles and minifies each player into a single js file, hosted on their platform, which you include on your page.

The code responsible for loading the player script asynchronously is triggered in the video component mounted() lifecycle hook. This is because the component accepts a 'player id' prop which means it could use one of many different video players (we use different players in different parts of the app). The player scripts are pretty large, so we don't want to load them unless absolutely necessary.

We have a 'blog post' view in the app which in some circumstances contains more than one video component, usually with the same player id. Without lazyloading, Vue could potentially render multiple video components simultaneously when this view is rendered, triggering multiple mounted() hooks and thus loading the same script multiple times.

Hope that makes sense.

@vgavro
Copy link
Contributor

vgavro commented Jul 18, 2018

Imho it's a legit and common usecase. You may use script2 with same script in different components that appears on same page, for example country info for country input and phone input, and you really don't want to track this in parent component.
I guess we can easily solve this by storing promise in Script2.loaded instead of "1", and we may even keep it after loading, so code can look like:

if (!Script2.load[src]) Script2.load[src] = Promise((resolve, reject... {
})
return Script2.load[src]

and remove Script2.loaded[src] = 1 from onload.

taoeffect added a commit that referenced this issue Jun 26, 2019
+ Better handling of simultaneously loaded components ([#12](#12) - thanks **[@vgavro](https://github.com/vgavro)**)
+ Emit vue events for `loaded` and `error` ([#31](#31) - thanks **[@vgavro](https://github.com/vgavro)**)
+ Updated all dev dependencies and switched from uglify to terser
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants