【问题标题】:Best way to use Google's hosted jQuery, but fall back to my hosted library on Google fail使用 Google 托管 jQuery 的最佳方式,但回退到我在 Google 上的托管库失败
【发布时间】:2010-11-04 02:14:03
【问题描述】:

什么是尝试加载 the hosted jQuery at Google(或其他 Google 托管的库)的好方法,但如果 Google 尝试失败则加载我的 jQuery 副本?

我并不是说 Google 不稳定。在某些情况下,Google 副本会被屏蔽(例如,显然在伊朗)。

我要设置一个计时器并检查 jQuery 对象吗?

两个副本都通过会有什么危险?

并不是真的在寻找诸如“只使用 Google 的”或“只使用你自己的”之类的答案。我理解这些论点。我也知道用户很可能缓存了 Google 版本。我正在考虑一般云的后备方案。


编辑:此部分已添加...

由于 Google 建议使用 google.load 加载 ajax 库,并在完成后执行回调,我想知道这是否是序列化此问题的关键。

我知道这听起来有点疯狂。我只是想弄清楚它是否可以以可靠的方式完成。


更新:jQuery 现在托管在 Microsoft 的 CDN 上。

http://www.asp.net/ajax/cdn/

【问题讨论】:

    标签: jquery cdn google-ajax-libraries


    【解决方案1】:

    你可以这样实现:

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
    
    <script>
           window.jQuery || document.write('<script src="/path/to/your/jquery"><\/script>');
    </script>
    

    这应该在您页面的 &lt;head&gt; 中,任何 jQuery 就绪事件处理程序都应该在 &lt;body&gt; 中以避免错误(尽管它不是万无一失的!)。

    使用 Google 托管的 jQuery 的另一个原因是,在某些国家/地区,Google 的域名被禁止。

    【讨论】:

    • javascript 下载不是已经阻塞(同步)了吗?因此,在我看来,双重副本问题不会成为问题。
    • Javascript 下载应该已经是同步的,正如 Matt Sherman 所说。否则,如果页面尝试执行依赖于仅下载一半的库的内联脚本,或者在库未完全下载和执行的情况下执行库扩展,则会出现许多问题。这也是 Yahoo YSlow 建议将 javascript 放在页面末尾的原因之一。这样它就不会阻止其他页面元素(包括样式和图像)的下载。至少,浏览器必须延迟执行才能顺序执行。
    • 来自验证器狂热者的小修复:JavaScript 中不允许使用字符串 '',因为它可能被误解为脚本标记的结尾(SGML 短标记表示法)。改为使用 ''。干杯,
    • 为了测试是否加载了 jQuery,(!window.jQuery) 工作正常,然后进行 typeof 检查。
    【解决方案2】:

    目前为止最简单、最干净的方法:

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="path/to/your/jquery"><\/script>')</script>
    

    【讨论】:

      【解决方案3】:

      这似乎对我有用:

      <html>
      <head>
      <script type="text/javascript" src="http://www.google.com/jsapi"></script>
      <script type="text/javascript">
      // has the google object loaded?
      if (window.google && window.google.load) {
          google.load("jquery", "1.3.2");
      } else {
          document.write('<script type="text/javascript" src="http://joecrawford.com/jquery-1.3.2.min.js"><\/script>');
      }
      window.onload = function() {
          $('#test').css({'border':'2px solid #f00'});
      };
      </script>
      </head>
      <body>
          <p id="test">hello jQuery</p>
      </body>
      </html>
      

      它的工作方式是使用调用http://www.google.com/jsapi 加载到window 对象上的google 对象。如果该对象不存在,我们假设对 Google 的访问失败。如果是这种情况,我们使用document.write 加载本地副本。 (在这种情况下,我使用的是我自己的服务器,请使用您自己的服务器进行测试)。

      我还测试了window.google.load 的存在 - 我还可以进行typeof 检查以查看事物是否是适当的对象或函数。但我认为这可以解决问题。

      这里只是加载逻辑,因为自从我发布了我正在测试的整个 HTML 页面后,代码突出显示似乎失败了:

      if (window.google && window.google.load) {
          google.load("jquery", "1.3.2");
      } else {
          document.write('<script type="text/javascript" src="http://joecrawford.com/jquery-1.3.2.min.js"><\/script>');
      }
      

      虽然我必须说,我不确定如果您的网站访问者担心这是否应该摆弄Google AJAX Libraries API

      有趣的事实我最初尝试在各种版本中为此使用 try..catch 块,但找不到像这样干净的组合。我很想看看这个想法的其他实现,纯粹作为一个练习。

      【讨论】:

      • 在这种情况下使用 google.load 有什么好处,而不是像 Rony 建议的那样直接加载 ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js ?我猜想直接加载它也会发现已删除库的问题(如果 Google 停止提供 JQuery 1.3.2 会怎样)。此外,Rony 的版本在获取 www.google.com/jsapi 之后会注意到网络问题,尤其是从缓存中加载 jsapi 时?可能需要使用 google.load 回调来确定(或者可能有一些返回值将 google.load 包含在 if(..) 中)。
      • 如果正在测试是否存在 Google.com,则可以进行网络调用,或者可以检查“网守”对象的存在。我正在做的是检查 google 对象及其“加载”功能。如果这两个都失败了,没有谷歌,我需要本地版本。 Rony 的版本实际上完全忽略了 www.google.com/jsapi URL,所以我不确定你为什么指出它会被获取。
      • 最后,只需要加载 jquery 库即可。任何 Google 库都不是必需的。在 Rony 的回答中,可以肯定地知道从 Google(或缓存)加载是否成功。但是在您检查“if (window.google && window.google.load)”时,仍然没有加载 jquery 库。 jquery库的实际加载没有经过验证?
      • 啊,我明白我是如何造成混乱的了。 “Rony 的版本在获取 www.google.com/jsapi 后发现网络问题”应该更好地阅读:“您的版本在获取 www.google.com/jsapi 后未发现网络问题”。
      • 我们最近切换到使用 Google 作为我们的 jQuery 主机;如果我们从被阻止的用户那里收到任何错误报告,我将使用您的答案的变体来重构我们的客户端代码。好答案!
      【解决方案4】:

      如果您的网站上嵌入了modernizr.js,您可以使用内置的yepnope.js 异步加载您的脚本——其中包括jQuery(带有后备)。

      Modernizr.load([{
          load : '//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'
      },{
          test : window.jQuery,
          nope : 'path/to/local/jquery-1.7.2.min.js',
          both : ['myscript.js', 'another-script.js'],
          complete : function () {
              MyApp.init();
          }
      }]);
      

      这会从 Google-cdn 加载 jQuery。然后检查 jQuery 是否加载成功。如果不是(“nope”),则加载本地版本。您的个人脚本也会被加载 - “both”表示加载过程是独立于测试结果启动的。

      当所有的加载过程都完成后,一个函数被执行,在这个例子中是'MyApp.init'。

      我个人更喜欢这种异步脚本加载方式。由于我在构建站点时依赖于modernizr 提供的功能测试,因此无论如何我都将它嵌入到站点中。所以实际上没有开销。

      【讨论】:

        【解决方案5】:

        这里有一些很好的解决方案,但我想进一步了解本地文件。

        在 Google 确实失败的情况下,它应该加载本地源,但服务器上的物理文件可能不一定是最佳选择。我提出这个是因为我目前正在实施相同的解决方案,只是我想回退到由数据源生成的本地文件。

        我这样做的原因是,在跟踪我从 Google 加载的内容与我在本地服务器上的内容时,我想有所了解。如果我想更改版本,我想让我的本地副本与我尝试从 Google 加载的内容保持同步。在一个有很多开发人员的环境中,我认为最好的方法是自动化这个过程,这样人们所要做的就是更改配置文件中的版本号。

        这是我提出的理论上应该可行的解决方案:

        • 在应用程序配置文件中,我将存储 3 项内容:库的绝对 URL、JavaScript API 的 URL 和版本号
        • 编写一个类来获取库本身的文件内容(从应用配置中获取 URL),并将其存储在我的数据源中,并带有名称和版本号
        • 编写一个处理程序,将我的本地文件从数据库中拉出并缓存该文件,直到版本号更改。
        • 如果它确实发生了变化(在我的应用程序配置中),我的类将根据版本号提取文件内容,将其作为新记录保存在我的数据源中,然后处理程序将启动并提供新版本。

        理论上,如果我的代码编写正确,我需要做的就是更改我的应用配置中的版本号,然后中提琴!您有一个自动化的后备解决方案,您不必在服务器上维护物理文件。

        大家怎么看?也许这有点矫枉过正,但它可能是维护 AJAX 库的一种优雅方法。

        橡子

        【讨论】:

          【解决方案6】:
          if (typeof jQuery == 'undefined') {
          // or if ( ! window.jQuery)
          // or if ( ! 'jQuery' in window)
          // or if ( ! window.hasOwnProperty('jQuery'))    
          
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = '/libs/jquery.js';
          
            var scriptHook = document.getElementsByTagName('script')[0];
            scriptHook.parentNode.insertBefore(script, scriptHook);
          
          }
          

          在您尝试从 CDN 包含 Google 的副本之后。

          在 HTML5 中,您不需要设置 type 属性。

          你也可以使用...

          window.jQuery || document.write('<script src="/libs/jquery.js"><\/script>');
          

          【讨论】:

            【解决方案7】:

            您可能希望使用本地文件作为最后的手段。

            目前看来jQuery自己的CDN不支持https。如果是这样,您可能希望先从那里加载。

            所以这是顺序: 谷歌 CDN => 微软 CDN => 您的本地副本。

            <!-- load jQuery from Google's CDN -->
            <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> 
            <!-- fallback to Microsoft's Ajax CDN -->
            <script> window.jQuery || document.write('<script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.3.min.js">\x3C/script>')</script> 
            <!-- fallback to local file -->
            <script> window.jQuery || document.write('<script src="Assets/jquery-1.8.3.min.js">\x3C/script>')</script> 
            

            【讨论】:

              【解决方案8】:

              有条件地加载最新/旧的 jQuery 版本和回退:

              <!--[if lt IE 9]>
                  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
                  <script>window.jQuery || document.write('<script src="/public/vendor/jquery-legacy/dist/jquery.min.js">\x3C/script>')</script>
              <![endif]-->
              <!--[if gte IE 9]><!-->
                  <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
                  <script>window.jQuery || document.write('<script src="/public/vendor/jquery/dist/jquery.min.js">\x3C/script>')</script>
              <!--<![endif]-->
              

              【讨论】:

                【解决方案9】:
                • 第 1 步:jQuery 是否加载失败? (检查jQuery变量)

                How to check a not-defined variable in JavaScript

                • 第 2 步:动态导入(备份)javascript 文件

                How do I include a JavaScript file in another JavaScript file?

                【讨论】:

                  【解决方案10】:

                  由于谷歌的封禁问题,我更喜欢使用微软的cdn http://www.asp.net/ajaxlibrary/cdn.ashx

                  【讨论】:

                    【解决方案11】:

                    对于那些使用 ASP.NET MVC 5 的人,在您的 BundleConfig.cs 中添加此代码以启用 jquery 的 CDN:

                    bundles.UseCdn = true;
                    Bundle jqueryBundle = new ScriptBundle("~/bundles/jquery", "//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js").Include("~/Scripts/jquery-{version}.js");
                    jqueryBundle.CdnFallbackExpression = "window.jQuery";
                    bundles.Add(jqueryBundle);
                    

                    【讨论】:

                    • 如果CDN有integritycrossorigin属性怎么办,比如这个:&lt;script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"&gt;&lt;/script&gt;?
                    【解决方案12】:

                    更新:
                    这个答案被证明是错误的。真正的解释请看cmets。


                    大部分问题都已经回答了,但至于最后一部分:

                    两个副本都通过会有什么危险?

                    真的没有。您会浪费带宽,下载第二个无用的副本可能会增加几毫秒的时间,但如果它们都通过,则不会造成实际伤害。当然,您应该使用上述技术来避免这种情况。

                    【讨论】:

                    • 实际上,根据this question,两次加载jQuery会导致很多问题。
                    • 何不自己测试一下,手动加载两次jquery库。那么答案就会揭晓。
                    • 到底为什么错了? @ShadowCat7 你能更具体地说明它引起的问题吗?我在您链接的问题中明确指出的唯一问题是“清除所有以前加载的插件”。但这不应该适用于连续两次加载相同的 jQuery 文件,对吗?我之所以问,是因为这里针对本地回退的其他解决方案非常复杂,并且 document.write 在某些places 中被诽谤为evil
                    【解决方案13】:

                    我做了一个 Gist,如果它还没有加载,它应该动态加载 jQuery,如果源失败,它会继续回退(从许多答案拼接在一起):https://gist.github.com/tigerhawkvok/9673154

                    请注意,我计划更新要点,但不更新这个答案,因为它的价值!

                    /* See https://gist.github.com/tigerhawkvok/9673154 for the latest version */
                    function cascadeJQLoad(i) { // Use alternate CDNs where appropriate to load jQuery
                        if (typeof(i) != "number") i = 0;
                        // the actual paths to your jQuery CDNs
                        var jq_paths = [
                            "ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js",
                            "ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.0.min.js"
                        ];
                        // Paths to your libraries that require jQuery
                        var dependent_libraries = [
                            "js/c.js"
                        ];
                        if (window.jQuery === undefined && i < jq_paths.length) {
                            i++;
                            loadJQ(jq_paths[i], i, dependent_libraries);
                        }
                        if (window.jQuery === undefined && i == jq_paths.length) {
                            // jQuery failed to load
                            // Insert your handler here
                        }
                    }
                    
                    /***
                     * You shouldn't have to modify anything below here
                     ***/
                    
                    function loadJQ(jq_path, i, libs) { //load jQuery if it isn't already
                        if (typeof(jq_path) == "undefined") return false;
                        if (typeof(i) != "number") i = 1;
                        var loadNextJQ = function() {
                            var src = 'https:' == location.protocol ? 'https' : 'http';
                            var script_url = src + '://' + jq_path;
                            loadJS(script_url, function() {
                                if (window.jQuery === undefined) cascadeJQLoad(i);
                            });
                        }
                        window.onload = function() {
                            if (window.jQuery === undefined) loadNextJQ();
                            else {
                                // Load libraries that rely on jQuery
                                if (typeof(libs) == "object") {
                                    $.each(libs, function() {
                                        loadJS(this.toString());
                                    });
                                }
                            }
                        }
                        if (i > 0) loadNextJQ();
                    }
                    
                    function loadJS(src, callback) {
                        var s = document.createElement('script');
                        s.src = src;
                        s.async = true;
                        s.onreadystatechange = s.onload = function() {
                            var state = s.readyState;
                            try {
                                if (!callback.done && (!state || /loaded|complete/.test(state))) {
                                    callback.done = true;
                                    callback();
                                }
                            } catch (e) {
                                // do nothing, no callback function passed
                            }
                        };
                        s.onerror = function() {
                            try {
                                if (!callback.done) {
                                    callback.done = true;
                                    callback();
                                }
                            } catch (e) {
                                // do nothing, no callback function passed
                            }
                        }
                        document.getElementsByTagName('head')[0].appendChild(s);
                    }
                    
                    /*
                     * The part that actually calls above
                     */
                    
                    if (window.readyState) { //older microsoft browsers
                        window.onreadystatechange = function() {
                            if (this.readyState == 'complete' || this.readyState == 'loaded') {
                                cascadeJQLoad();
                            }
                        }
                    } else { //modern browsers
                        cascadeJQLoad();
                    }
                    

                    【讨论】:

                      【解决方案14】:

                      Google 托管的 jQuery

                      • 如果您关心较旧的浏览器,主要是 IE9 之前的 IE 版本,这是最广泛兼容的 jQuery 版本
                      &lt;script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"&gt;&lt;/script&gt;
                      • 如果你不关心 oldIE,这个更小更快:
                      &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"&gt;&lt;/script&gt;

                      备份/后备计划!

                      • 无论哪种方式,您都应该使用回退到本地,以防 Google CDN 失败(不太可能)或在您的用户访问您的网站的位置(可能性稍大)被阻止,例如伊朗或有时是中国。李>
                      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
                      <script>if (!window.jQuery) { document.write('<script src="/path/to/your/jquery"><\/script>'); }
                      </script>
                      

                      参考:http://websitespeedoptimizations.com/ContentDeliveryNetworkPost.aspx

                      【讨论】:

                      • 注意通过不安全的协议加载脚本会打开 XSS 攻击向量。
                      【解决方案15】:

                      我认为应该将字符串中的最后一个

                      <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js"></script>
                      <script>window.jQuery || document.write('<script src="js/jquery-2.0.0.min.js">\x3C/script>')</script>
                      

                      【讨论】:

                        【解决方案16】:
                        if (typeof jQuery == 'undefined')) { ...
                        

                        或者

                        if(!window.jQuery){
                        

                        如果没有加载 cdn 版本将无法正常工作,因为浏览器将在此条件下运行,并且在此期间仍会下载需要 jQuery 的其余 javascripts 并返回错误。解决方案是通过该条件加载脚本。

                            <script src="http://WRONGPATH.code.jquery.com/jquery-1.4.2.min.js" type="text/javascript"></script><!--  WRONGPATH for test-->
                          <script type="text/javascript">
                          function loadCDN_or_local(){
                            if(!window.jQuery){//jQuery not loaded, take a local copy of jQuery and then my scripts
                              var scripts=['local_copy_jquery.js','my_javascripts.js'];
                              for(var i=0;i<scripts.length;i++){
                              scri=document.getElementsByTagName('head')[0].appendChild(document.createElement('script'));
                              scri.type='text/javascript';
                              scri.src=scripts[i];
                            }
                          }
                          else{// jQuery loaded can load my scripts
                            var s=document.getElementsByTagName('head')[0].appendChild(document.createElement('script'));
                            s.type='text/javascript';
                            s.src='my_javascripts.js';
                          }
                          }
                          window.onload=function(){loadCDN_or_local();};
                          </script>
                        

                        【讨论】:

                        【解决方案17】:

                        几乎所有公共 CDN 都非常可靠。但是,如果您担心被阻止的 google 域,那么您可以简单地回退到替代 jQuery CDN但是,在这种情况下,您可能更愿意以相反的方式进行操作,并使用其他一些 CDN 作为您的首选选项并回退到 Google CDN 以避免失败的请求和等待时间:

                        <script src="https://pagecdn.io/lib/jquery/3.2.1/jquery.min.js"></script>
                        <script>
                           window.jQuery || document.write('<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"><\/script>');
                        </script>
                        

                        【讨论】:

                          【解决方案18】:

                          在 ASP.NET 中使用 Razor 语法,此代码提供回退支持并与虚拟根一起使用:

                          @{var jQueryPath = Url.Content("~/Scripts/jquery-1.7.1.min.js");}
                          <script type="text/javascript">
                              if (typeof jQuery == 'undefined')
                                  document.write(unescape("%3Cscript src='@jQueryPath' type='text/javascript'%3E%3C/script%3E"));
                          </script>
                          

                          或者做一个助手(helper overview):

                          @helper CdnScript(string script, string cdnPath, string test) {
                              @Html.Raw("<script src=\"http://ajax.aspnetcdn.com/" + cdnPath + "/" + script + "\" type=\"text/javascript\"></script>" +
                                  "<script type=\"text/javascript\">" + test + " || document.write(unescape(\"%3Cscript src='" + Url.Content("~/Scripts/" + script) + "' type='text/javascript'%3E%3C/script%3E\"));</script>")
                          }
                          

                          并像这样使用它:

                          @CdnScript("jquery-1.7.1.min.js", "ajax/jQuery", "window.jQuery")
                          @CdnScript("jquery.validate.min.js", "ajax/jquery.validate/1.9", "jQuery.fn.validate")
                          

                          【讨论】:

                          • 我从不喜欢 Razor,但它看起来像一个混淆器,除了它使代码更长而不是更短(它是 this 的两倍。
                          • @maaartinus:这不是苹果对苹果的比较。您提到的 BenjaminRH 的答案是针对单个 CDN 托管的脚本。使用CdnScript 帮助程序,每个脚本 只需要一行代码。您拥有的脚本越多,收益就越大。
                          • 当然......这只是一个咆哮。但是,我想这不是最佳方式。如果有任何失败,我会完全忽略 CDN 并切换到所有脚本的后备。我不确定这是否可行,因为我不知道加载究竟是如何工作的。
                          • @maaartinus:由于每个 CDN 脚本加载都可能独立失败,因此您必须分别检查每个加载。没有可靠的方法来检查单个 CDN,然后从 CDN 和本地加载所有脚本。
                          • 让我担心的情况是 CDN 站点的故障导致许多负载的等待时间。所以我想要try { for (Script s : ...) cdnLoad(s); } catch (...) { for (Script s : ...) ownLoad(s); } 之类的东西。将其翻译成一堆ifs 可能是一场噩梦。
                          【解决方案19】:

                          虽然写document.write("&lt;script&gt;&lt;/script&gt;") 似乎更容易让jQuery 退避,但Chrome 在这种情况下会给出验证错误。所以我更喜欢打破“脚本”这个词。所以它变得像上面一样更安全。

                          <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.1.min.js"></script>
                          <script>if (typeof jQuery === "undefined") {
                             window.jqFallback = true;
                             document.write("<scr"+"ipt src='http://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js'></scr"+"ipt>");
                          } </script>
                          

                          对于长期问题,最好记录 JQuery 回退。在上面的代码中,如果第一个 CDN 不可用,则从另一个 CDN 加载 JQuery。但是您可能想知道错误的 CDN 并将其永久删除。 (这种情况是非常特殊的情况)另外最好记录回退问题。因此,您可以使用 AJAX 发送错误的案例。由于没有定义 JQuery,你应该使用 vanilla javascript 来进行 AJAX 请求。

                          <script type="text/javascript">
                              if (typeof jQuery === 'undefined' || window.jqFallback == true) {
                                  // XMLHttpRequest for IE7+, Firefox, Chrome, Opera, Safari
                                  // ActiveXObject for IE6, IE5
                                  var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
                                  var url = window.jqFallback == true ? "/yourUrl/" : "/yourUrl2/";
                                  xmlhttp.open("POST", url, true);
                                  xmlhttp.send();
                              }
                          </script>
                          

                          【讨论】:

                            【解决方案20】:

                            无法从您无法控制的外部数据存储中加载资源是很困难的。寻找丢失的函数作为一种避免超时的方法是完全错误的,如下所述: http://www.tech-101.com/support/topic/4499-issues-using-a-cdn/

                            【讨论】:

                            • 上面的链接坏了。
                            【解决方案21】:

                            另一个使用 cdnjs.cloudflare.com 替换 ajax.googleapis.com 的备用方案:

                            (function (doc, $)
                            {
                                'use strict';
                            
                                if (typeof $ === 'undefined')
                                {
                                    var script = doc.querySelector('script[src*="jquery.min.js"]'),
                                        src = script.src.replace('ajax.googleapis.com', 'cdnjs.cloudflare.com');
                            
                                    script.parentNode.removeChild(script);
                                    doc.write('<script src="' + src + '"></script>');
                                }
                            })(document, window.jQuery || window.Zepto);
                            
                            • 您可以通过在字符串中指定 jQuery 版本来坚持使用它
                            • 非常适合不适用于 HTML 片段的资产管理
                            • 在野外测试 - 非常适合来自中国的用户

                            【讨论】:

                            • 您能否详细说明以下语句:“您不必关心 jQuery 版本”?
                            • 版本是 URL 的一部分,这种方法不会触及... jquery/3.x.x/jquery.min.js
                            • 当 jQuery 升级到版本 4 并引入向后不兼容的更改时,这是否有可能导致损坏?
                            • -1 因为如果 jQuery 引入了您的脚本尚不支持的破坏性更改,除非指定版本,否则这将导致损坏。
                            • @lookaji 我认为您不了解后备。它确实会替换托管它的域,并且根本不会触及文件名/版本。
                            【解决方案22】:

                            您可以使用如下代码:

                            <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
                            <script>window.jQuery || document.write('<script type="text/javascript" src="./scripts/jquery.min.js">\x3C/script>')</script>
                            

                            但您也可以使用一些库来为您的脚本设置几个可能的后备方案并优化加载过程:

                            • basket.js
                            • RequireJS
                            • 是的

                            例子:

                            basket.js 我认为目前最好的变种。将在 localStorage 中缓存您的脚本,这将加快下一次加载。最简单的调用:

                            basket.require({ url: '/path/to/jquery.js' });
                            

                            这将返回一个承诺,您可以在错误时执行下一次调用,或在成功时加载依赖项:

                            basket
                                .require({ url: '/path/to/jquery.js' })
                                .then(function () {
                                    // Success
                                }, function (error) {
                                    // There was an error fetching the script
                                    // Try to load jquery from the next cdn
                                });
                            

                            RequireJS

                            requirejs.config({
                                enforceDefine: true,
                                paths: {
                                    jquery: [
                                        '//ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min',
                                        //If the CDN location fails, load from this location
                                        'js/jquery-2.0.0.min'
                                    ]
                                }
                            });
                            
                            //Later
                            require(['jquery'], function ($) {
                            });
                            

                            是的

                            yepnope([{
                              load: 'http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js',
                              complete: function () {
                                if (!window.jQuery) {
                                  yepnope('js/jquery-2.0.0.min.js');
                                }
                              }
                            }]);
                            

                            【讨论】:

                              【解决方案23】:

                              您永远不需要使用个人副本。这是我完整的腰带和大括号脚本。

                              <!DOCTYPE html>
                              <html lang="en">
                                  <head>
                                      <meta charset="utf-8"/>
                                      <title>jQuery</title>
                                      <!-- EMBED JQUERY USING GOOGLE APIs -->
                                      <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
                              
                                      <!-- IF THAT FAILS EMBED JQUERY USING CLOUDFLARE CDN -->
                                      <script type="text/javascript">
                                          window.jQuery || document.write('<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"><\/script>');
                                      </script>
                              
                                      <!-- IF THAT FAILS ************* HOW??? *********** EMBED JQUERY FROM MICROSOFT -->
                                      <script type="text/javascript">
                                          window.jQuery || document.write('<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.6.0.min.js"><\/script>');
                                      </script>
                              
                                      <!-- IF THAT FAILS ************* WOW!!! *********** EMBED JQUERY FROM JQUERY.COM -->
                                      <script type="text/javascript">
                                          window.jQuery || document.write('<script src="https://code.jquery.com/jquery-3.6.0.min.js"><\/script>');
                                      </script>
                              
                                      <!-- IF THAT FAILS ************* LET'S STOP!!! *********** EMBED JQUERY FROM PERSONAL COPY -->
                                      <script type="text/javascript">
                                          window.jQuery || document.write('<script src="jquery.min.js"><\/script>');
                                      </script>
                                  </head>
                                  <body>
                              
                              
                                  </body>
                              </html>
                              

                              【讨论】:

                                猜你喜欢
                                • 2011-05-01
                                • 1970-01-01
                                • 2015-04-06
                                • 2013-01-11
                                • 2012-01-14
                                • 2016-01-13
                                • 2010-11-12
                                • 1970-01-01
                                • 2010-12-01
                                相关资源
                                最近更新 更多