外部CDN脚本失败时如何异步回退? (异步/延迟)

时间:2017-02-18 14:37:07

标签: javascript html html5 cdn html-rendering

我想要以异步方式下载/执行这些脚本以防止页面呈现阻塞:

< script src =" jQuery CDN "的延迟>< /脚本>
< script src =" Bootstrap CDN "的延迟>< /脚本>

Bootstrap依赖于jQuery,因此必须按此顺序执行。这就是我使用defer的原因,但我的问题也适用于async

我如何异步回退到我自己托管的jQuery或Bootstrap版本,或者任何CDN托管的脚本?

我见过this related question on Stackoverflow,但这些解决方案不起作用,因为:

  1. 它依赖document.write,不能用于async / defer脚本;或者:
  2. 它不会立即执行回退脚本,导致无法加载jQuery时出现问题,并且在jQuery回退之前加载了依赖于jQuery的其他脚本。
  3. 我尝试了以下内容,但这也导致了上述问题#2:

    <script src="failing external CDN script" defer onerror="
        var script = document.createElement('script');
        script.async = false;
        script.src = 'my own hosted version the script';
        document.body.appendChild(script);
    "></script>
    

1 个答案:

答案 0 :(得分:2)

  

我有这些脚本,我想异步下载/执行以防止页面呈现阻塞

最简单的方法就是将它们放在页面的末尾,就在结束</body>标记之前。它们不会在那里进行渲染,你可以轻松地进行后备:

<script src="jQuery CDN"></script>
<script>
if (typeof jQuery === "undefined") {
    // ...add your local version instead...
}
</script>

您在评论中已经说过,如果script之前没有</body>,PageSpeed就会抱怨defer个标签。相对而言,它没有(注意到code.jquery.com的链接被故意破坏):

<!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>

从PageSpeed获得100/100(如果你正确托管 - 压缩等)。

现在,如果我在底部有CSS link,我还会在顶部设置内联CSS来设置上面的内容。 (但我可能不会打扰,我只是在顶部有link并接受命中。我只把它放在该示例的底部,因为PageSpeed将JS和CSS集中在它的警告上主题,我想证明script </body>之前defer没有触发错误......)

但是如果你想使用error,你必须听取问题中显示的load事件。当然,这意味着您必须暂停添加依赖于jQuery的脚本,直到您从原始脚本或其替换中获得<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> ,因为您无法插入进入管道。 E.g:

addDependencies

...其中script根据脚本为事物添加# csv gets loaded etc. import = CsvImport.new import.logger += 'Starting import' ActiveRecord::Base.transaction do import.logger += 'CSV loaded, starting import' csv_array.each_with_index do |row, index| begin unless importer.has_key?(row[0]) import.logger += 'Key not found' raise StandardError end result = CsvImporter.import_line(row[0]) import.logger += 'Imported line #{index} successfully' if result rescue import.logger += 'Transaction aborted!' end end import.logger += 'Transaction successful!' end 个标记。