tserkov / vue-plugin-load-script

A Vue plugin for injecting remote scripts.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Request for clarification of instructions

NiallTracey opened this issue · comments

The docs are rather confusing, as there is no explicit explanation or example of how to call a script after loading it.

I am trying to use this module in an SFC application that I'm developing with NPM inside Visual Studio Code to access the Jitsi videoconference API.

This is in my mounted() code block:

    Vue.loadScript("https://meet.jit.si/external_api.js")
        .then(() => {
            let api = new JitsiMeetExternalAPI("meet.jit.si",{ roomName: 'dummy', parentNode: document.querySelector('#jitsi') })
            Vue.set(outerthis,"api",api)
        })
        .catch(error => {
            // Failed to fetch script
            console.log(error)
        });

...but it complains that JitsiMeetExternalAPI was not defined. If I put in a dummy declaration for JitsiMeetExternalAPI at the start of the script, that doesn't help, as it tries to use that instead, and complains that it isn't a constructor at runtime. The library has definitely loaded -- I can access the JitsiMeetExternalAPI from the top level; I just don't see it in my Vue code.

If the problem is just that it won't work with a linter as the identifier isn't defined until runtime, I think that's definitely worth mentioning in the docs, because most of us will have linting on by default. However, I'm left wondering whether this will work at all on a compiled SFC application (i.e. not being served dynamically on node), as compilation mungs identifiers, and what's it going to do with an undefined one?

Some clarification of this in the instructions would be very much appreciated.

And obviously the answer is that I just need to qualify the scope as window.JitsiMeetExternalAPI and everything works fine.

I think it's worth including a note in the instructions to that effect:

To access a function from the loaded script, you may need to prefix the function name with window. to access the full browser scope and ensure compatibility across devices.

commented

Thanks for your response -- that's very helpful and far more elegant than prefixing every call with window. .

"Unless I've misunderstood something, I don't see this as an issue with this
library or it's documentation, but rather your understanding of scope and
linters.
"

Well, think of it this way. Your library is incredibly useful, as it enables coders to do things they previously were unable to do. That means many of us have never been in a position to need that level of familiarity with linters or scoping rules. Globals are deliberately avoided in many tutorials on Vue for reasons of design philosophy. I discovered this module was via a suggestion on StackOverflow, and one comment in response to it (that went unanswered) was "How to call a function from the loaded script?" so I'm not the only one who got confused.

Adding a brief note in the instructions for the aid of such people will make your library easier for people to use.

Here's my suggestion, based on what you've just told me, continuing your example of the Google Maps API, and using an example from Google's API docs:

Once imported, javascript libraries can be accessed by their usual name, eg

  this.map = new google.maps.Map(document.getElementById("map") as HTMLElement, {
    center: { lat: -34.397, lng: 150.644 },
    zoom: 8,
   });

However, if you are using a linter to check your code, this may report as an undefined variable. You will need to instruct your linter to ignore this variable or function. Instructions for ESlint here

If you are unable to resolve this in your linter, adding window. before the name of the variable or function you are attempting to access will also correct this problem, e.g.:

  this.map = new window.google.maps.Map(document.getElementById("map") as HTMLElement, {
    center: { lat: -34.397, lng: 150.644 },
    zoom: 8,
   });

So no, there's nothing wrong with your instructions, and again thanks for making this incredibly useful library available. I'm just suggesting a small usability improvement.

Well, I must say it also took me a while to understand what to do with this plugin, I event uninstalled it because it basically does nothing. Until I understood it loads the scripts in the global scope. So maybe a line or two about that fact wouldn't hurt, linter or not, scope understanding or not