CDN विफल होने पर स्थानीय स्टाइलशीट (स्क्रिप्ट नहीं) पर कैसे वापस आएं


108

मैं एक सीडीएन पर jQuery के मोबाइल स्टाइलशीट से लिंक कर रहा हूं और अगर सीडीएन विफल रहता है तो स्टाइलशीट के अपने स्थानीय संस्करण पर वापस आना चाहूंगा। स्क्रिप्ट के लिए समाधान अच्छी तरह से जाना जाता है:

<!-- Load jQuery and jQuery mobile with fall back to local server -->
<script src="http://code.jquery.com/jquery-1.6.3.min.js"></script>
<script type="text/javascript">
  if (typeof jQuery == 'undefined') {
    document.write(unescape("%3Cscript src='jquery-1.6.3.min.js'%3E"));
  }
</script>

मैं एक स्टाइल शीट के लिए कुछ ऐसा ही करना चाहूंगा:

<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.css" />

मुझे यकीन नहीं है कि अगर एक समान दृष्टिकोण प्राप्त किया जा सकता है क्योंकि मुझे यकीन नहीं है कि स्क्रिप्ट को लिंक करते समय ब्राउज़र उसी तरह से ब्लॉक करता है जैसा कि स्क्रिप्ट को लोड करते समय करता है (शायद स्क्रिप्ट टैग में स्टाइलशीट लोड करना संभव है और फिर इसे पेज में इंजेक्ट करें)?

तो मेरा सवाल यह है: अगर सीडीएन विफल रहता है तो मैं कैसे सुनिश्चित करूं कि एक स्टाइलशीट को स्थानीय रूप से लोड किया जाए?


2
मैं यह जानना चाहता हूं कि क्या यह संभव है ... यदि मैं वास्तव में सीडीएन नीचे होने के बारे में सोचता हूं, तो मैं सिर्फ स्थानीय होस्टिंग का उपयोग करूंगा।
फॉस्को

2
@ स्तेफ़ान केंडल, मुझे लगता है कि सही कथन यह है कि उनकी साइट सीडीएन की तुलना में नीचे जाने की संभावना से अधिक होगी
शॉन

सबसे अच्छा तरीका: stackoverflow.com/questions/26192897/…
nmit026

जवाबों:


63

क्रॉस-ब्राउज़र परीक्षण नहीं किया गया है लेकिन मुझे लगता है कि यह काम करेगा। हालांकि आपके द्वारा jquery को लोड करने के बाद होना चाहिए, या आपको इसे सादे जावास्क्रिप्ट में फिर से लिखना होगा।

<script type="text/javascript">
$.each(document.styleSheets, function(i,sheet){
  if(sheet.href=='http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.css') {
    var rules = sheet.rules ? sheet.rules : sheet.cssRules;
    if (rules.length == 0) {
      $('<link rel="stylesheet" type="text/css" href="path/to/local/jquery.mobile-1.0b3.min.css" />').appendTo('head');
    }
 }
})
</script>

अच्छा समाधान, एक मुद्दा यह संबोधित नहीं करता है कि क्या सीडीएन लोड करने के लिए बहुत धीमा है ... शायद किसी तरह का टाइमआउट?
जॉर्ज यूएपी 22'11

2
के लिए code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css , मैं नियमों = अशक्त मिलता है, भले ही यह सही ढंग से लोड किया गया है। मैं Chrome 26 का उपयोग कर रहा हूं और मुझे लगता है कि यह इसलिए है क्योंकि स्क्रिप्ट क्रॉस डोमेन है?
सादाफज़

8
समाधान वास्तव में सभी CDN / Stylesheets के लिए काम नहीं करता है, उदाहरण के लिए CSSStyleSheetjs ऑब्जेक्ट जो bootstrapcdn.com से आते हैं, सभी मेरे ब्राउज़र में खाली हैं rulesऔर cssRulesफ़ील्ड (Chrome 31)। UPD : यह वास्तव में एक क्रॉसडोमेन मुद्दा हो सकता है, उत्तर में css फ़ाइल भी मेरे लिए काम नहीं करती है।
मक्सीम वी।

3
यह भी onerrorघटना का उपयोग कर अच्छा समाधान है । stackoverflow.com/questions/30546795/…
रासायनिक प्रोग्रामर

2
क्या यह सीएसएस दूसरे डोमेन से लोड के लिए काम करता है? नहीं, आप की गणना नहीं कर सकते हैं .rules/ .cssRulesबाह्य शैलीपत्रक के लिए। jsfiddle.net/E6yYN/13
सलमान एक

29

मुझे लगता है कि सवाल का पता लगाने के लिए है कि एक स्टाइलशीट भरी हुई है या नहीं। एक संभावित दृष्टिकोण इस प्रकार है:

1) अपनी सीएसएस फ़ाइल के अंत में एक विशेष नियम जोड़ें, जैसे:

#foo { display: none !important; }

2) अपने HTML में संबंधित div जोड़ें:

<div id="foo"></div>

3) दस्तावेज़ तैयार होने पर, जांचें कि क्या #fooदिखाई दे रहा है या नहीं। यदि स्टाइलशीट लोड की गई थी, तो यह दिखाई नहीं देगी।

यहाँ डेमो - लोड jquery-ui चिकनाई विषय; स्टाइलशीट में कोई नियम नहीं जोड़ा गया है।


42
एक चतुर समाधान के लिए +1। केवल समस्या यह है कि कोई आम तौर पर एक स्टाइल शीट के अंत में एक पंक्ति नहीं जोड़ सकता है जो किसी के CDN पर होस्ट की जाती है
Jannie Theunissen

2
दुर्भाग्य से, हम CDN फ़ाइलों के लिए अपनी कक्षाओं में टाइप नहीं कर सकते। हो सकता है कि हम पहले से मौजूद एक का उपयोग करने का प्रयास कर सकें।
med

1
मुझे यह एक बहुत पसंद है, धन्यवाद। यह वास्तव में काफी शक्तिशाली है। जाहिर है मैं सीडीएन स्टाइलशीट में हेरफेर नहीं कर सकता, लेकिन मुझे पता है कि कौन सी कक्षाएं इस्तेमाल की जा रही हैं, इसलिए मैंने यह दिखाने के लिए कोड में संशोधन किया कि क्या वे दिखाई दे रहे हैं - वास्तव में बहुत चालाक हैं :)
Nosnibor

3
एनबी: आपको वास्तव में बाहरी सीएसएस में एक नया नियम नहीं जोड़ना है। बस एक मौजूदा नियम का उपयोग करें जिसका व्यवहार ज्ञात हो। अपने डेमो में मैं यूआई-हेल्पर-छिपा हुआ वर्ग का उपयोग करता हूं जो कि तत्व को छिपाना है, मैं तब जांचता हूं कि क्या तत्व पृष्ठ लोड पर छिपा हुआ है।
सलमान ए

28

यह मानते हुए कि आप css और jQuery के लिए एक ही CDN का उपयोग कर रहे हैं, क्यों न केवल एक टेस्ट करें और यह सब पकड़ें ??

<link href="//ajax.googleapis.com/ajax/libs/jqueryui/1/themes/start/jquery-ui.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script type="text/javascript">
    if (typeof jQuery == 'undefined') {
        document.write(unescape('%3Clink rel="stylesheet" type="text/css" href="../../Content/jquery-ui-1.8.16.custom.css" /%3E'));
        document.write(unescape('%3Cscript type="text/javascript" src="/jQuery/jquery-1.6.4.min.js" %3E%3C/script%3E'));
        document.write(unescape('%3Cscript type="text/javascript" src="/jQuery/jquery-ui-1.8.16.custom.min.js" %3E%3C/script%3E'));
    }
</script>

1
क्या मैं पूछ सकता हूं कि शुरू में बिना तार के इस्तेमाल के साथ क्या समस्या है document.write("<script type='text/javascript' src='path/to/file.js'>")?
जैक टक

2
@JackTuck: पार्सर <script>जेएस स्ट्रिंग के अंदर और बाहर पाए जाने वाले के बीच अंतर नहीं कर सकता है । आमतौर पर यही कारण है कि आप <\/script>CDN की कमियों के लिए टैग लिखते समय भी देखते हैं ।
ब्रैड क्रिस्टी

6
-1 why not just do one test and catch it all?- क्योंकि एक लाख कारण हैं कि एक असफल हो सकता है, और दूसरे सफल होते हैं।
टिमटिमा

7

यह आलेख बूटस्ट्रैप css के लिए कुछ समाधान सुझाता है http://eddmann.com/posts/providing-local-js-and-css-resources-for-cdn-fallbacks/

वैकल्पिक रूप से यह फॉन्टव्यू के लिए काम करता है

<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<script>
    (function($){
        var $span = $('<span class="fa" style="display:none"></span>').appendTo('body');
        if ($span.css('fontFamily') !== 'FontAwesome' ) {
            // Fallback Link
            $('head').append('<link href="https://stackoverflow.com/css/font-awesome.min.css" rel="stylesheet">');
        }
        $span.remove();
    })(jQuery);
</script>

फ़ॉन्ट विस्मयकारी 5 के साथ इसका उपयोग करने के इच्छुक लोगों के लिए, आप 'FontAwesome' (यदि क्लॉज में) को 'Font Awesome 5 Free' में बदलना चाहते हैं (यदि आप फ्री फोंट का उपयोग कर रहे हैं)। अन्यथा, यह ठीक काम करना चाहिए।
जेसन क्लार्क

4

आप स्टाइलशीट के अस्तित्व के लिए परीक्षण करने में सक्षम हो सकते हैं document.styleSheets

var rules = [];
if (document.styleSheets[1].cssRules)
    rules = document.styleSheets[i].cssRules
else if (document.styleSheets[i].rules)
    rule= document.styleSheets[i].rules

आपके द्वारा उपयोग किए जा रहे CSS फ़ाइल के लिए कुछ विशिष्ट के लिए परीक्षण करें।


4

एक onerrorउस के लिए उपयोग कर सकते हैं :

<link rel="stylesheet" href="cdn.css" onerror="this.onerror=null;this.href='local.css';" />

इस this.onerror=null;मामले में अंतहीन छोरों से बचने के लिए है कि यह स्वंय उपलब्ध नहीं है। लेकिन इसका उपयोग कई कमियां होने के लिए भी किया जा सकता है।

हालाँकि, यह वर्तमान में केवल फ़ायरफ़ॉक्स और क्रोम में काम करता है।


3

यहाँ katy lavallee के उत्तर का विस्तार दिया गया है। मैंने चर टकरावों को रोकने के लिए सब कुछ स्व-निष्पादित फ़ंक्शन सिंटैक्स में लपेट दिया है। मैंने स्क्रिप्ट को एक लिंक से गैर-विशिष्ट बना दिया है। IE, अब "डेटा-फ़ॉलबैक" यूआरएल विशेषता के साथ किसी भी स्टाइलशीट लिंक को स्वचालित रूप से पार्स किया जाएगा। आपको पहले की तरह इस स्क्रिप्ट में url को हार्ड-कोड नहीं करना है। ध्यान दें कि यह <head>तत्व के अंत के बजाय तत्व के अंत में चलाया जाना चाहिए <body>, अन्यथा यह FOUC का कारण बन सकता है ।

http://jsfiddle.net/skibulk/jnfgyrLt/

<link rel="stylesheet" type="text/css" href="broken-link.css" data-fallback="broken-link2.css">

(function($){
    var links = {};

    $( "link[data-fallback]" ).each( function( index, link ) {
        links[link.href] = link;
    });

    $.each( document.styleSheets, function(index, sheet) {
        if(links[sheet.href]) {
            var rules = sheet.rules ? sheet.rules : sheet.cssRules;
            if (rules.length == 0) {
                link = $(links[sheet.href]);
                link.attr( 'href', link.attr("data-fallback") );
            }
        }
    });
})(jQuery);

1
मुझे एनकैप्सुलेशन पसंद है, लेकिन सामान्य तौर पर आप एक क्रॉस-डोमेन स्टाइलशीट के लिए शीट.ट्रूल्स का निरीक्षण नहीं कर सकते। आप अभी भी इस सामान्य विचार का उपयोग कर सकते हैं, लेकिन एक अलग जांच करने की आवश्यकता है।
जॉन विनपाल

साथ document.styleSheets[i].ownerNode.datasetआप उपयोग कर सकते हैं <link data-* />गुण
एल्विन Kesler

2

क्या आप वास्तव में एक सीडीएन विफल होने पर सीएसएस को लोड करने के लिए इस जावास्क्रिप्ट मार्ग से नीचे जाना चाहते हैं?

मैंने सोचा नहीं है कि सारे प्रदर्शन निहितार्थ हैं, लेकिन आप सीएसएस लोड होने पर और पृष्ठ लोड प्रदर्शन के लिए सामान्य रूप से नियंत्रण खोने जा रहे हैं, सीएसएस पहली चीज है जिसे आप HTML के बाद डाउनलोड करना चाहते हैं।

इसे बुनियादी ढांचे के स्तर पर क्यों नहीं संभालना है - अपने स्वयं के डोमेन नाम को सीडीएन में मैप करें, इसे एक छोटा टीटीएल दें, सीडीएन पर फाइलों की निगरानी करें (जैसे वॉचमाउस या कुछ और का उपयोग करके), यदि सीडीएन विफल रहता है, तो DNS को बैकअप साइट में बदलें।

अन्य विकल्प जो स्थिर सामग्री पर "हमेशा के लिए कैश" करने में मदद कर सकते हैं, लेकिन इसकी कोई गारंटी नहीं है कि ब्राउज़र उन्हें निश्चित रूप से रखेगा या ऐप-कैश का उपयोग करेगा।

वास्तव में जैसा कि किसी ने सबसे ऊपर कहा है, यदि आपका CDN अविश्वसनीय है तो एक नया प्राप्त करें

एंडी


7
सीडीएन विश्वसनीय हो सकता है, लेकिन विकास पर्यावरण इंटरनेट कनेक्शन नहीं;)
आइसब्रेकर

1

इन कार्यों को देखें:

$.ajax({
    url:'CSS URL HERE',
    type:'HEAD',
    error: function()
    {
        AddLocalCss();
    },
    success: function()
    {
        //file exists
    }
});

और यहाँ वेनिला जावास्क्रिप्ट संस्करण है:

function UrlExists(url)
{
    var http = new XMLHttpRequest();
    http.open('HEAD', url, false);
    http.send();
    return http.status!=404;
}
if (!UrlExists('CSS URL HERE') {
AddLocalCss();
}

अब वास्तविक कार्य:

function AddLocalCss(){
document.write('<link rel="stylesheet" type="text/css" href=" LOCAL CSS URL HERE">')
}

बस सुनिश्चित करें कि AddLocalCss को सिर में कहा जाता है।

आप इस उत्तर में बताए गए किसी एक तरीके का उपयोग करने पर भी विचार कर सकते हैं :

AJAX का उपयोग कर लोड करें

$.get(myStylesLocation, function(css)
{
   $('<style type="text/css"></style>')
      .html(css)
      .appendTo("head");
});

गतिशील रूप से निर्मित लोड का उपयोग करें

$('<link rel="stylesheet" type="text/css" href="'+myStylesLocation+'" >')
   .appendTo("head");
Load using dynamically-created <style>

$('<style type="text/css"></style>')
    .html('@import url("' + myStylesLocation + '")')
    .appendTo("head");

या

$('<style type="text/css">@import url("' + myStylesLocation + '")</style>')
    .appendTo("head");

हां, कम से कम आधुनिक ब्राउज़र में, मुझे IE6 के बारे में निश्चित नहीं है।

क्या पूरी चीज़ को डाउनलोड करने के बजाय सिर्फ जांचने का कोई तरीका है?
शॉन मैक्लेन

ओपी अनुरोध करने का एकमात्र संभावित कारण अतिरिक्त नेटवर्क ट्रैफ़िक से बचना है। यह अतिरिक्त नेटवर्क ट्रैफ़िक बनाता है।
स्टीफन केंडल

@stefan केंडल: नहीं, यह भी संभव कारण नहीं है कि वह सुनिश्चित करे कि फाइलें लोड हो जाएं।

यदि केवल यही चिंता थी, तो आप सीडीएन का उपयोग नहीं करेंगे। सिर्फ हेडर का परीक्षण करना बेहतर है, लेकिन मुझे पूरा यकीन है कि अधिकांश CDN और आपका ब्राउज़र XSS की अनुमति नहीं देंगे।
स्टीफन केंडल

-1

मैं शायद yepnope.js की तरह कुछ का उपयोग करेंगे

yepnope([{
  load: 'http:/­/ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js',
  complete: function () {
    if (!window.jQuery) {
      yepnope('local/jquery.min.js');
    }
  }
}]);

वाचम से लिया गया


10
@BenSchwarz, इसका मतलब यह नहीं है कि आप कुछ अप्रासंगिक कोड पेस्ट कर सकते हैं जो किसी भी तरह से पूछे गए सवाल का जवाब नहीं देता है।
एलिकन सी

-8
//(load your cdn lib here first)

<script>window.jQuery || document.write("<script src='//me.com/path/jquery-1.x.min.js'>\x3C/script>")</script>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.