I have these scripts that I want to download/execute asynchronously to prevent page render blocking
The simplest way to do that is just to put them at the end of the page, just before the closing </body> tag. They don't render-block there, and you can do the fallback trivially:
<script src="jQuery CDN"></script>
<script>
if (typeof jQuery === "undefined") {
// ...add your local version instead...
}
</script>
You've said in a comment that PageSpeed will complain about script tags just before </body> if they don't have defer. With respect, it doesn't (note that the link to code.jquery.com is intentionally broken):
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Example</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="favicon.png">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
Content here, turns green on click
</div>
</div>
</div>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-2.2.4.mn.js"></script>
<script>
if (typeof jQuery === "undefined") {
document.write('<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"><\/script>');
}
</script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script>
$(".col-md-12").on("click", function() {
$(this).css("color", "green");
});
</script>
</body>
</html>
That gets 100/100 from PageSpeed (if you host it properly — compression, etc.).
Now, if I had the CSS link at the bottom, I'd also have inline CSS at the top to style the above-the-fold content. (But I probably wouldn't bother, I'd just have the link at the top and accept the hit. I only put it at the bottom of that example because PageSpeed lumps together JS and CSS in its warning on the topic, and I wanted to demonstrate that script just before </body> doesn't trigger that error...)
But if you want to use defer, you'd have to listen for the error event as shown in your question. And of course, that means you have to hold off adding the scripts that are dependent on jQuery until you've had load from the original script or its replacement, since you can't insert into the pipeline. E.g.:
<script src="failing external CDN script" defer onerror="
var script = document.createElement('script');
script.async = false;
script.onload = addDependencies;
script.src = 'my own hosted version the script';
document.body.appendChild(script);
" onload="addDependencies()"></script>
...where addDependencies adds script tags for the things depending on the script.
` tag? They don't render-block there, and you can do the fallback without difficulty.
– T.J. Crowder Feb 18 '17 at 14:43` tag.
– Rudey Feb 18 '17 at 14:57` doesn't show up as an issue.
– T.J. Crowder Feb 18 '17 at 14:58` while it shouldn't.
– Rudey Feb 18 '17 at 15:33