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