0

I want to include jQuery from CDN into my code. I also want to create a fallback. My original solution was to check if CDN has failed, and if so use document.write to insert the fallback <script> into the DOM.

Now Google is saying not to use document.write so instead I have changed my fallback function to dynamically insert the local <script> path into the DOM:

<script>
    function fallback(id, localScript) {
        fallBackNode = document.getElementById(id);
        // insert local jQuery path, right after fallback (does not work)
        fallBackNode.insertAdjacentHTML("afterend", "<script src='" + localScript + "'><\/script>");
        
        // insert local jQuery path, (works)
        //document.write('<script src="' + localPath + '"><\/script>');
    }
</script>

// jQuery CDN
<script src="https://code.jquery.com/jquery-3.6.0.9-INVALID_CDN.min.js"></script>
// jQuery fallback
<script id="jqueryfallback">window.jQuery || fallback('jqueryfallback', '/Scripts/jquery-3.6.0.min.js');
// jQuery ui CDN
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script></script>

Both of the above options (i.e. using document.write and using fallBackNode.insertAdjacentHTML) produce exactly the same result, they insert my local path right after the fallback check, as shown below:

<script id="jqueryfallback">window.jQuery || fallback('jqueryfallback', '/Scripts/jquery-3.6.0.min.js');</script>
<script src="/Scripts/jquery-3.6.0.min.js"></script> // <-- both solutions insert this line here

However when I use document.write everything works fine and the local jQuery gets loaded before jQuery.ui... but if I use the fallBackNode.insertAdjacentHTML option, I get the following error in jQuery.ui:

enter image description here

It seems like, jQuery.ui which is the next library, does not wait for the local jQuery to be inserted into DOM, and throws error... how can I resolve this issue?

Hooman Bahreini
  • 14,480
  • 11
  • 70
  • 137
  • does this answer your question https://stackoverflow.com/questions/538745/how-to-tell-if-a-script-tag-failed-to-load or https://stackoverflow.com/questions/7383163/how-to-fallback-to-local-stylesheet-not-script-if-cdn-fails ? – Harsh Gundecha May 28 '21 at 06:54
  • @HarshGundecha: not really... plus that question is using `document.write()` which I want to avoid. – Hooman Bahreini May 28 '21 at 07:00
  • Yeah i did see that, but to me it seems same problem since it boils down to failure in loading resource so i though it might be helpful. – Harsh Gundecha May 28 '21 at 07:04
  • Does this answer your question? [Best way to use Google's hosted jQuery, but fall back to my hosted library on Google fail](https://stackoverflow.com/questions/1014203/best-way-to-use-googles-hosted-jquery-but-fall-back-to-my-hosted-library-on-go) – restlessmodem May 28 '21 at 07:55
  • @restlessmodem: the answers to this question mostly use `document.write` which is no longer a good solution, or use yepnope.js which is deprecated. – Hooman Bahreini May 28 '21 at 09:00

1 Answers1

1

I was interested in this idea, so I tried a simple script loading sequence. You set up the array of main/fallback scripts in the sequence you want them to load. Not sure how production ready it is, but let me know if it helps.

const scripts = [{
    main: "https://badlink.com/nothing.js",
    fallback: "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
  },
  {
    main: "https://badlink.com/nothing.js",
    fallback: "https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
  }
];

let scriptcounter = 0;

function loadScripts() {
  if (scriptcounter < scripts.length) {
    loadScript(scriptcounter);

  }
}

function loadScript(index, fallback) {
  let thescript = fallback ? scripts[index].fallback : scripts[index].main
  let myScript = document.createElement("script");
  myScript.setAttribute("src", thescript);
  document.body.appendChild(myScript);

  myScript.addEventListener("load", scriptLoaded, false);
  myScript.addEventListener("error", scriptError, false);


  function scriptError() {
    console.log("Script error for ", thescript);
    if (fallback) console.log("Fallback failed, stopping");
    else loadScript(index, true)
  }

  function scriptLoaded() {
    console.log("Script loaded - ", thescript);
    scriptcounter++;
    loadScripts()
  }
}

window.onload = function() {
  loadScripts()
}
Kinglish
  • 23,358
  • 3
  • 22
  • 43