GoogleのホストされたjQueryを使用する最良の方法ですが、Googleのホストされたライブラリにフォールバックできません
-
06-07-2019 - |
質問
GoogleでホストされているjQuery (または他のGoogleホストライブラリ)、ただし、Googleの試行が失敗した場合、jQueryのコピーを読み込みますか?
Googleが不安定だと言っているわけではありません。 Googleのコピーがブロックされる場合があります(たとえば、イランでは明らかに)。
タイマーを設定してjQueryオブジェクトを確認しますか?
両方のコピーが通過する危険性は何ですか?
実際に<!> quotのような回答を探しているのではなく、Googleのものを使用してください<!> quot;または<!> quot;独自のものを使用してください。<!> quot;私はそれらの議論を理解しています。また、ユーザーがGoogleバージョンをキャッシュしている可能性が高いことも理解しています。一般的にクラウドのフォールバックについて考えています。
編集:この部分を追加...
Googleはgoogle.loadを使用してajaxライブラリをロードすることを提案し、完了時にコールバックを実行するので、それがこの問題をシリアル化するための鍵かどうか疑問に思っています。
ちょっとおかしく聞こえるかもしれません。信頼できる方法で実現できるかどうかを把握しようとしています。
更新:jQueryがMicrosoftのCDNでホストされるようになりました。
>解決
次のように達成できます:
<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>
これはページの<head>
にある必要があり、jQuery対応のイベントハンドラはエラーを回避するために<body>
にある必要があります(万全ではありません!)。
GoogleがホストするjQueryを 使用しないもう1つの理由は、一部の国ではGoogleのドメイン名が禁止されていることです。
他のヒント
これを行う最も簡単でクリーンな方法:
<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>
これは私にとってはうまくいくようです:
<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/を呼び出すgoogle
オブジェクトを使用することですjsapi はwindow
オブジェクトにロードします。そのオブジェクトが存在しない場合、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ブロックを使用しようとしましたが、これほどクリーンな組み合わせは見つかりませんでした。このアイデアの他の実装を、純粋に演習として見てみたいと思います。
サイトに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が正常にロードされたかどうかがチェックされます。そうでない場合(<!> quot; nope <!> quot;)、ローカルバージョンがロードされます。また、個人用スクリプトも読み込まれます-<!> quot; both <!> quot;ロードプロセスがテストの結果とは無関係に開始されることを示します。
すべてのロードプロセスが完了すると、「MyApp.init」の場合、関数が実行されます。
個人的には、この方法の非同期スクリプトの読み込みを好みます。また、サイトを構築する際にmodernizrが提供する機能テストに依存しているため、とにかくそれをサイトに埋め込みました。したがって、実際にはオーバーヘッドはありません。
ここにはいくつかの優れたソリューションがありますが、ローカルファイルに関してさらに一歩進めたいと思います。
Googleが失敗するシナリオでは、ローカルソースをロードする必要がありますが、サーバー上の物理ファイルが必ずしも最適なオプションであるとは限りません。現在同じソリューションを実装しているため、これを取り上げます。データソースによって生成されるローカルファイルにフォールバックしたいだけです。
この理由は、Googleから読み込んだものとローカルサーバーにあるものを追跡することに関して、ある程度の心を持ちたいということです。バージョンを変更したい場合は、ローカルコピーをGoogleからロードしようとしているものと同期したままにします。多くの開発者がいる環境では、構成ファイルのバージョン番号を変更するだけでよいので、このプロセスを自動化することが最善のアプローチだと思います。
理論的には機能するはずの提案されたソリューションを次に示します。
- アプリケーション構成ファイルには、ライブラリの絶対URL、JavaScript APIのURL、バージョン番号の3つのものを保存します
- ライブラリ自体のファイルの内容を取得するクラスを作成し(アプリの構成からURLを取得)、名前とバージョン番号と共にデータソースに保存します
- ローカルファイルをデータベースから取り出し、バージョン番号が変更されるまでファイルをキャッシュするハンドラーを作成します。
- (アプリの構成で)変更された場合、クラスはバージョン番号に基づいてファイルの内容を取得し、データソースに新しいレコードとして保存します。その後、ハンドラーが起動して新しいバージョンを提供します。
理論的には、コードが適切に記述されていれば、アプリの設定でバージョン番号を変更してから、ヴィオラを変更するだけです!自動化されたフォールバックソリューションがあり、サーバー上の物理ファイルを維持する必要はありません。
誰もがどう思いますか?これはやり過ぎかもしれませんが、AJAXライブラリを保守するエレガントな方法かもしれません。
ドングリ
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>');
ローカルファイルを最後の手段として使用できます。
現在、jQueryのCDNはhttpsをサポートしていません。もしそうなら、最初にそこからロードしたいかもしれません。
これがシーケンスです: Google CDN = <!> gt; Microsoft CDN = <!> gt; ローカルコピー。
<!-- 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>
条件付きで最新/レガシー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]-->
- ステップ1:jQueryはロードに失敗しましたか? (
jQuery
変数を確認してください)
- ステップ2:JavaScriptファイルを動的にインポート(バックアップ)する
Googleの禁止問題のため、Microsoftのcdnを使用したい http://www.asp.net/ajaxlibrary/cdn.ashx
これについての素晴らしい説明があります!
ロードの遅延とタイムアウトも実装します!
http://happyworm.com/blog/2010/01/28/a-simple-and-robust-cdn-failover-for-jquery-14-in-one-line/
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);
更新:
この答えは間違っていました。実際の説明については、コメントをご覧ください。
ほとんどの質問に回答しましたが、最後の部分については
両方のコピーが通過する危険性は何ですか?
本当にありません。帯域幅を浪費し、2番目の役に立たないコピーをダウンロードするために数ミリ秒を追加する可能性がありますが、両方が通過しても実際の害はありません。もちろん、上記の手法を使用してこれを回避する必要があります。
jQueryがまだロードされていない場合、jQueryを動的にロードするGistを作成し、ソースが失敗した場合、フォールバックに進みます(多くの回答からまとめられます): https://gist.github.com/tigerhawkvok/9673154
Gistの更新を続ける予定ですが、この答えではなく、価値があるためです!
/* 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();
}
Google Hosted jQuery
- 古いブラウザ、主にIE9より前のIEのバージョンを気にする場合、これは最も広く互換性のあるjQueryバージョンです
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
- 古い<!>#8217; oldIEを気にしない場合、これは小さくて高速です:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
バックアップ/フォールバックプラン!
- いずれにしても、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
最後の<!> ltをエスケープする必要があると思います。文字列で\ x3Cに。ブラウザはを見ると、これをスクリプトブロックの終わりと見なします(HTMLパーサーはJavaScriptを認識していないため、文字列に表示されるものと、実際にスクリプトを終了するものとを区別できません)素子)。そのため、HTMLページ内にあるJavaScriptに文字通り表示されると、(最良の場合)エラーが発生し、(最悪の場合)大きなセキュリティホールになります。
<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>
if (typeof jQuery == 'undefined')) { ...
または
if(!window.jQuery){
cdnバージョンがロードされていない場合、ブラウザはこの条件を実行し、jQueryを必要とする残りのjavascriptをダウンロードしてエラーを返すため、機能しません。解決策は、その条件でスクリプトをロードすることでした。
<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>
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 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")
document.write("<script></script>")
の記述はjQueryバックオフの方が簡単に思えますが、Chromeではその場合に検証エラーが発生します。ですから、<!> quot; script <!> quot;ワード。したがって、上記のように安全になります。
<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が利用できない場合、JQueryは別のCDNからロードされます。しかし、その誤ったCDNを知り、永久に削除したい場合があります。 (このケースは非常に例外的なケースです)また、フォールバックの問題をログに記録することをお勧めします。そのため、AJAXを使用してエラーのあるケースを送信できます。 JQueryは定義されていないため、AJAXリクエストにはバニラjavascriptを使用する必要があります。
<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>
外部データストアからリソースを制御できないほどロードすることは困難です。ここで説明されているように、タイムアウトの発生を回避する手段として、欠落している機能を探すことは完全に誤りです。 http://www.tech-101.com/ support / topic / 4499-issues-using-a-cdn /
ajax.googleapis.com を cdnjs.cloudflare.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スニペットでは機能しないAsset Managementに最適
- テスト済み-中国のユーザーに最適です
次のようなコードを使用できます。
<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
- yepnope
例:
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
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');
}
}
}]);
ほとんどすべてのパブリックCDNは非常に確実です。ただし、ブロックされたGoogleドメインが心配な場合は、 PageCDN のような他のパブリックCDNにフォールバックできます。 CDNJS または jsDelivr :
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
window.jQuery || document.write('<script src="https://pagecdn.io/lib/jquery/3.2.1/jquery.min.js"><\/script>');
</script>
ただし、このような場合、他の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>