tony99nyr / twitch-embed

Make Twitch's embed video script available on npm.
4 stars 3 forks source link

Why can't this script be loaded dynamically using the following methods? #3

Open evolross opened 1 month ago

evolross commented 1 month ago

I'm battling with this now, trying to get Twitch's https://embed.twitch.tv/embed/v1.js to load dynamically.

I've tried all of the following and none of them will add Twitch to window similar to how it does if you just add the following to the <body> element:

<script src="https://embed.twitch.tv/embed/v1.js"></script>

I tried doing the following:

//  Calling jquery's getScript()
$.getScript(...);

//  Dynamically adding a <script> element
let s = document.createElement("script");
s.type = "text/javascript";
s.src = "https://player.twitch.tv/js/embed/v1.js";
$("head").append(s);

The above will load the script in the browser's Sources tab, but it will not add Twitch to the global window. Why is that? Just curious if you could explain.

evolross commented 1 month ago

I'm also trying to get the latest https://embed.twitch.tv/embed/v1.js to work so I'm curious what modifications you made.

evolross commented 4 weeks ago

For anyone who comes across this too, I was able to put the latest Twitch JS library (as of 08/16/2024) https://embed.twitch.tv/embed/v1.js into my project, then access it like this without any changes to the source:

import Twitch from "your/path/to/locally/saved/twitch/embed_v1.js";
window.Twitch = Twitch;  // Optional
evolross commented 4 weeks ago

I also figured out how to dynamically load the script using $.getScript(...). The problem is the Twitch code has this line at the top that tries to detect its environment and how it will make Twitch (which is t()) available:

"object" == typeof exports && "object" == typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define([], t) : "object" == typeof exports ? exports.Twitch = t() : e.Twitch = t()

Upon using a little Github Copilot to break that down, the script detects exports and module in my Meteor application and then sets module.exports = t() which sets Twitch as an export of this module. It never makes it to last else of the inline if which is e.Twitch = t() which would set Twitch into the global window object.

After figuring this out, it was a matter if finding where the script's exports are at. Logging modules after the $.getScript(...) success showed that Twitch was inside of modules.parent.parent.exports which ended up being the client entry point JS file of my Meteor app.

So in the .done callback of $.getScript(...) I needed to do:

//  Access the set export from the Twitch Embed script
const { Twitch } = require("/client/main.js");

//  Set the Twitch object to the window for the rest of the app to use as normal
window.Twitch = Twitch;

So there is it. Dynamically loading the Twitch Embed JS library with no source modifications.