-
-
Save MrJackdaw/d111b5bcdfc8b71afba8ba6c55b3168f to your computer and use it in GitHub Desktop.
// Example usage of Inject-Script.js | |
// Example 1: Load a script from an external URL. (preferred method) | |
// You can call this in a React/Vue/whatever component lifecycle, or wherever. | |
// makes sense. Window globals (e.g. `window.YT`) will be available after calling this. | |
await injectScriptBySrc("https://www.youtube.com/iframe_api", "yt"); | |
// now you can use `window.YT` methods and properties in your code. | |
// Example 2: Load the raw text content of a script into a page | |
// You can also call this wherever it makes sense, though it is probably a | |
// terrible idea to trigger code this way, and you *should* likely be ashamed. | |
const myShamefulJS = ` | |
const something = 1; | |
console.log( something ); | |
` | |
injectScriptContents(myShamefulJS); | |
// logs "1" to console after the above line executes. |
/** | |
* @file Inject-Script | |
* @description DYNAMICALLY INJECT EXTERNAL SCRIPT DEPENDENCIES INTO YOUR WEB APP | |
* | |
* NOTE: Track page-session scripts (i.e. scripts that should be reloaded with the page). | |
* You can track as few or as many script dependencies as needed: YouTube is provided as an | |
* example below. | |
*/ | |
// (example for tracking YT script dependency) | |
let YouTubeLoaded = false; | |
// (example if loading Google Charts script into your app) | |
// let GoogleCharts = false; | |
/** | |
* Inject a `<script />` tag with the supplied contents into the page's | |
* html. This will execute `contents` immediately. You should ideally prefer | |
* `injectScriptBySrc( ... )` over this method. If it MUST be used, modify | |
* this file to track any required scripts that have to be loaded in this way. | |
* @param {string} contents Script tag contents | |
*/ | |
export function injectScriptContents(contents) { | |
const scrpt = document.createElement('script'); | |
scrpt.innerHTML = contents; | |
const lastElem = document.head.lastChild; | |
document.head.insertBefore(scrpt, lastElem); | |
// Update module state to track that this script has been loaded. e.g.: | |
// | |
// YouTubeLoaded = (key === "yt"); | |
// GoogleChartsLoaded = (key === "gc"); // etc | |
} | |
/** | |
* Inject a `<script />` tag by `src` attribute into the page's | |
* html. This will execute `contents` immediately. | |
* @param {string} src External URL for Script source | |
* @param {string|undefined} key An internal identifier that helps track whether | |
* this script has been loaded in your app (so you don't load it multiple times) | |
*/ | |
export async function injectScriptBySrc(src, key) { | |
// IMPORTANT: Check if script has been loaded; exit if true. For example: | |
// if (key === "yt" && YouTubeLoaded) return; | |
// Load script from source and inject into page | |
const scrpt = document.createElement('script'); | |
scrpt.src = src; | |
scrpt.id = `${key}-script`; | |
const lastElem = document.head.lastChild; | |
document.head.insertBefore(scrpt, lastElem); | |
// Update module state to track that this script has been loaded. e.g.: | |
// | |
// YouTubeLoaded = (key === "yt"); | |
// GoogleChartsLoaded = (key === "gc"); // etc | |
} | |
/** | |
* Identify and remove <script /> tag by its id from the page | |
* @param. {string} key Internal identifier for script, so that the module can | |
* track its loaded/unloaded status | |
*/ | |
export function unmountScript(key: string) { | |
const id = `${key}-script`; | |
const script = document.getElementById(id); | |
if (script) script.remove(); | |
// Update module state to track that this script has been unloaded. e.g.: | |
// | |
// switch (key) { | |
// case "gc": return void (GoogleChartsLoaded = false); | |
// case "yt": return void (YouTubeLoaded = false); | |
// default: break; | |
// } | |
} |
Hey @mrdark69! I never saw your comment, so apologies for the extremely belated response.
I haven't used react-hot-loader
before, so I'm not sure I would be able to help. (Please note I didn't create this script: just made a few modifications from the original, linked at the top.) I noticed however that the original gist had a bug, where nothing was happening in ScriptCache.onLoad
because ...nothing was being called. I updated the code, though I'm not sure if it helps. If not, describe your issue here and I'd be happy to help take a look when I can.
Public Service Announcement
The gist and example above have been completely changed to reflect my latest approach to this problem.
While I still haven't used react-hot-loader
, all comments prior to 2025 are aimed at a previous gist. See revisions for previous versions.
Nice solution!!
But I have one issues when integrate with react-hot-loader.
Could you advise?