引用CDN內(nèi)容的方法總結(jié)

1.1.1 摘要

CDN相信大家都聽(tīng)說(shuō)過(guò),甚至使用過(guò)相關(guān)的技術(shù),也許有些人會(huì)回答“沒(méi)有聽(tīng)說(shuō)過(guò)和使用過(guò)該技術(shù)”,真的是這樣嗎?
CDN的全稱是Content Delivery Network烹吵,即內(nèi)容分發(fā)網(wǎng)絡(luò)。其目的是通過(guò)在現(xiàn)有的Internet中增加一層新的網(wǎng)絡(luò)架構(gòu)桨武,將網(wǎng)站的內(nèi)容發(fā)布到最接近用戶的網(wǎng)絡(luò)"邊緣"肋拔,使用戶可以就近取得所需的內(nèi)容,解決 Internet網(wǎng)絡(luò)擁擠的狀況呀酸,提高用戶訪問(wèn)網(wǎng)站的響應(yīng)速度凉蜂。
看完上面一大串的定義,我們可以把CDN簡(jiǎn)單的描述為:內(nèi)容分發(fā)性誉,解決網(wǎng)絡(luò)擁擠和提供網(wǎng)站相應(yīng)速度窿吩。
其實(shí),CDN并不神秘甚至我們?cè)谌粘i_(kāi)發(fā)過(guò)程中常常使用到該技術(shù)错览,例如:引用網(wǎng)絡(luò)腳本庫(kù)(如:jQuery)和網(wǎng)絡(luò)圖片資源等纫雁。
我們經(jīng)常發(fā)現(xiàn)許多網(wǎng)站都從Google的CDN中引用相應(yīng)的Javascript庫(kù),但很多網(wǎng)站都沒(méi)有考慮如果CDN內(nèi)容加載失敗的情況倾哺,我們并不是說(shuō)Google的CDN很脆弱轧邪,只是不怕萬(wàn)一只怕一萬(wàn)。
在接下來(lái)的博文中悼粮,我們將想大家介紹防范CDN內(nèi)容加載的方法闲勺。

目錄

  • 基本方法
  • HTML5 Boilerplate中的解決方法
  • Javascript加載器
  • ASP.NET Web Form 4.5
  • AspNet.ScriptManager.jQuery包
  • ASP.NET Web Optimization包

1.1.2 正文

基本方法
檢查CDN內(nèi)容是否加載成功的基本的方法,我們可以在腳本代碼后添加代碼判斷該類型或變量是否存在扣猫,如果不存證明CDN加載失敗,那么我們的程序就應(yīng)該加載本地腳本翘地,下面我們以加載jQuery庫(kù)為例申尤,具體實(shí)現(xiàn)如下:

<!-- Adds google cdn reference -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>

<!-- Cdn fail refers to local library -->
<script type="text/javascript">
    if (typeof jQuery == 'undefined') {
        document.write(unescape("%3Cscript src='js/jquery-2.0.0.min.js' type='text/javascript'%3E%3C/script%3E"));
    }
</script>

上面,我們引用了 Google CDN 的jQuery庫(kù)衙耕,接著我們?cè)谀_本代碼后添加了一個(gè) if 語(yǔ)句來(lái)判斷 jQuery 庫(kù)是否加載成功昧穿,如果沒(méi)有加載成功我們動(dòng)態(tài)加載本地 jQuery 庫(kù)。
其中橙喘,我們?cè)?document.write 方法中直接使用了URL編碼时鸵,把“<”編碼為“%3C”,接著我們?cè)偈褂?unescape() 方法把字符串還原過(guò)來(lái)。


圖1字符編碼

上圖饰潜,我們通過(guò) unescape() 方法把字符串轉(zhuǎn)換回來(lái)初坠,我們可以看到輸出是一個(gè)正常的腳本引用代碼。
現(xiàn)在彭雾,我們有一個(gè)疑問(wèn)就是“為什么不使用常規(guī)字符碟刺,而是要使用字符編碼呢?”薯酝,其實(shí)這是有原因的半沽,這意味著我們代碼將可以在XML、XHTML或HTML中正常運(yùn)行吴菠,而無(wú)需把代碼包含在 CDATA 中(具體請(qǐng)參考這里)者填。

HTML5 Boilerplate中的解決方法
接下來(lái),我們將介紹使用“協(xié)議省略”的引用地址和簡(jiǎn)化本地加載代碼做葵,在介紹之前占哟,首先讓我們了解使用“協(xié)議省略”的引用地址的優(yōu)點(diǎn)。
我們知道使用安全的引用地址對(duì)于確保信息安全是無(wú)可厚非的蜂挪,但過(guò)度地使用SSL緩存靜態(tài)資源例如:jQuery庫(kù)重挑,也會(huì)導(dǎo)致加載的性能降低;出于同樣的原因?yàn)g覽器需要對(duì)這些資源進(jìn)行加密棠涮,而且大多數(shù)瀏覽器默認(rèn)不緩存通過(guò)SSL方式獲取的文件谬哀。
更糟糕的是,即使用戶已經(jīng)有一個(gè)本地緩存副本在磁盤(pán)上严肪,但通過(guò)HTTP請(qǐng)求從Google的CDN獲取jQuery文件史煎,不能被同一請(qǐng)求不同協(xié)議HTTPS使用,也就是說(shuō)驳糯,對(duì)于同一請(qǐng)求不同協(xié)議要保存兩個(gè)緩存文件篇梭。
Http請(qǐng)求的URL地址:
http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js
下面是使用Https請(qǐng)求的URL地址:
https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js
當(dāng)我們?cè)诔R?guī)的Http頁(yè)面中通過(guò)Https方式來(lái)引用Google CDN的jQuery庫(kù)將導(dǎo)致緩存性能下降,我們應(yīng)該盡量避免在Http頁(yè)面中引用不必要的Https內(nèi)容酝枢。
在RFC3986中的第4.2節(jié)規(guī)定合法的URL省略了協(xié)議(Http或Http)還是合法的恬偷,當(dāng)一個(gè)URL的協(xié)議被省略時(shí),瀏覽器將使用基本的文檔的協(xié)議帘睦,通過(guò)這種方式袍患,我們可以更加靈活地指定URL地址。所以我們可以通過(guò)以下的方式引用jQuery庫(kù)竣付。

<!-- Adds protocol-less google cdn reference -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>

上面的代碼看起來(lái)奇怪诡延,但“協(xié)議省略”的網(wǎng)址是引用第三方內(nèi)容的最好的方式,它可以通過(guò)Http或Https引用古胆。
當(dāng)頁(yè)面加載時(shí)肆良,對(duì)于非加密請(qǐng)求腳本會(huì)通過(guò)Http方式引用并且緩存起來(lái),以此同時(shí)對(duì)于加密請(qǐng)求腳本會(huì)根據(jù)“協(xié)議省略”方式使用Https引用內(nèi)容,所以使用“協(xié)議省略”的URL允許單個(gè)腳本更靈活地引用內(nèi)容惹恃。
接下來(lái)夭谤,我們繼續(xù)簡(jiǎn)化加載本地腳本的代碼,當(dāng)jQuery成功加載到頁(yè)面中座舍,它會(huì)創(chuàng)建一個(gè)全局的jQuery變量沮翔,我們可以通過(guò)window的jQuery屬性(window.jQuery)訪問(wèn)該變量的值,如果jQuery沒(méi)有加載成功曲秉,那么window.jQuery就是未定義的采蚀。
所以,我們可以把代碼簡(jiǎn)化成如下:

<!-- Adds protocol-less google cdn reference -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<!--<script src="http://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>

上面承二,我們使用了“||”運(yùn)算符判斷window.jQuery是否為未定義類型榆鼠,如果 window.jQuery 未定義執(zhí)行后面的代碼加載本地jQuery腳本,HTML5 Boilerplate 就使用以上的方法處理CDN內(nèi)容加載失敗的情況亥鸠。

Javascript加載器
有些人使用JavaScript加載器如:yepnope妆够,它是一個(gè)能夠根據(jù)輸入條件來(lái)選擇性異步加載資源文件的js腳本,可以在頁(yè)面上僅加載用戶需要的js或css负蚊,下面我們以加載jQuery為例子介紹yepnope的使用神妹,具體實(shí)現(xiàn)如下:

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');
        }
    }
}]);

上面,我們使用加載器 yepnope 把 jQuery 加載到頁(yè)面中家妆,接下來(lái)鸵荠,我們介紹使用 RequireJS 加載 jQuery,具體實(shí)現(xiàn)如下:

// Uses requestJS to add cdn reference.    
requirejs.config({
    enforceDefine: true,
    paths: {
        jquery: [
            '//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js',
            //If the CDN location fails, load from this location
            'js/jquery-2.0.0.min'
        ]
    }
});
//Later
require(['jquery'], function($) {
    // Your code here.
});

我們可以RequireJS加載器中使用“協(xié)議省略”的URL地址伤极,這樣我們可以避免前面提到的加密協(xié)議和非加密協(xié)議加密和緩存問(wèn)題了蛹找。
雖然,JS加載器也可以解決CDN內(nèi)容加載失敗的問(wèn)題哨坪,但僅僅為了防止CDN內(nèi)容加載失敗問(wèn)題而引入yepnope 或 RequireJS是沒(méi)有必要的庸疾。

ASP.NET Web Form 4.5
對(duì)于每個(gè)ASP.NET Web窗體開(kāi)發(fā)人員牵敷,我們需要了解在ASP.NET 4.5增加的新特性绝骚,其中就包含了處理CDN內(nèi)容加載失敗轉(zhuǎn)移加載本地內(nèi)容的特性挖函。
首先旭绒,我們?cè)陧?yè)面中添加ScriptManager控件,然后設(shè)置該控制的EnableCdn屬性為“True”犀填,接著我們添加需要加載的內(nèi)容名稱隐岛,下面以加載jQuery為例:

<!-- Set up cdn -->       
<asp:ScriptManager runat="server" EnableCdn="true">
    <Scripts>
        <asp:ScriptReference Name="jquery" />
    </Scripts>
</asp:ScriptManager>

上面螺垢,我們通過(guò) ScriptManager 控件指定加載 jQuery庫(kù)牵舱,但這里我們有一個(gè)疑問(wèn)首先是我們沒(méi)有指定加載 jQuery庫(kù)的URL地址,第二在加載失敗后缺虐,沒(méi)有指定本地 jQuery庫(kù)路徑芜壁。
現(xiàn)在,我們通過(guò)運(yùn)行頁(yè)面代碼查看 ScriptManager 生成的腳步代碼,具體代碼如下:

<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.2.js" type="text/javascript"></script>
<script type="text/javascript">
    //<![CDATA[
    (window.jQuery) || document.write('<script type="text/javascript" src="Scripts/jquery-1.8.2.js"><\/script>'); //]]>
</script>

通過(guò)上面的代碼慧妄,我們發(fā)現(xiàn)ScriptManager默認(rèn)加載jQuery庫(kù)的URL是 http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.2.js 而且一旦加載失敗它自動(dòng)到Scripts文件中加載本地腳步顷牌。
雖然這種方式簡(jiǎn)單而且省心,但它默認(rèn)是到微軟的CDN中加載內(nèi)容的塞淹,如果我們想使用Google的CDN呢窟蓝?難道微軟打算CDN也搞壟斷嗎?還有我們想使用jQuery 2.0.0庫(kù)應(yīng)該如何加載呢饱普?
其實(shí)运挫,我們可以通過(guò)自定義 ScriptResourceMapping 方式來(lái)指定加載的 CDN和 jQuery庫(kù),我們要在 Global.asax 文件中添加以下代碼:

var mapping = ScriptManager.ScriptResourceMapping;
// Map jquery definition to the Google CDN
mapping.AddDefinition("jquery", new ScriptResourceDefinition
{
    Path = "~/Scripts/jquery-2.0.0.min.js",
    DebugPath = "~/Scripts/jquery-2.0.0.js",
    CdnPath = "http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js",
    CdnDebugPath = "https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.js",
    CdnSupportsSecureConnection = true,
    LoadSuccessExpression = "window.jQuery"
});

上面套耕,我們定義了加載 Google的 CDN和 jQuery 2.0.0版本谁帕,接下來(lái)我們重新運(yùn)行頁(yè)面代碼查看 ScriptManager生成的腳步代碼是否對(duì)應(yīng)我們的設(shè)置。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
    //<![CDATA[
    (window.jQuery) || document.write('<script type="text/javascript" src="Scripts/jquery-2.0.0.js"><\/script>'); //]]>
</script>

現(xiàn)在冯袍,我們看到使用的是Google的CDN匈挖,并且加載jQuery的版本為2.0.0的。

AspNet.ScriptManager.jQuery包
在ASP.NET4.5中康愤,如果我們想使用jQuery 2.0.0或更新的版本儡循,其實(shí)我們可以通過(guò)使用AspNet.ScriptManager.jQuery包來(lái)管理引用庫(kù)的更新,其中它也包括配置CDN信息的功能征冷,如果我們要獲取最新的更新择膝,首先我們選擇工具->擴(kuò)展工具管理器->AspNet.ScriptManager.jQuery,然后更新包就可以獲取最新的jQuery庫(kù)资盅。

ASP.NET Web Optimization包
如果我們使用的是ASP.NET MVC程序调榄,同樣我們可以通過(guò)更新ASP.NET Web Optimization包來(lái)管理CDN配置信息。


接下來(lái)呵扛,我們?cè)诘?BundleConfig 中指定我們的 CdnPath 的 URL 地址每庆,打開(kāi) App_Start\BundleConfig.cs,我們可以看到里面有一個(gè) RegisterBundles() 方法今穿,下面是 RegisterBundles() 方法的一部分代碼:

/// <summary>
/// Sets up the jquery libs load path.
/// </summary>
/// <param name="bundles"></param>
public static void RegisterBundles(BundleCollection bundles)
{
    bundles.UseCdn = true;
    BundleTable.EnableOptimizations = true; //force optimization while debugging

    var jquery = new ScriptBundle("~/bundles/jquery", "http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js").Include(
            "~/Scripts/jquery-{version}.js");
    jquery.CdnFallbackExpression = "window.jQuery";
    bundles.Add(jquery);
    //...
}

1.1.3 總結(jié)

在本文中缤灵,我們向大家介紹了一些 CDN 內(nèi)容引用失敗的處理機(jī)制,就處理方式來(lái)說(shuō)蓝晒,我覺(jué)得 HTML5 Boilerplate 的解決方法不但簡(jiǎn)潔腮出,而且不用引入第三方庫(kù)。
同時(shí)我們也介紹了使用“協(xié)議省略”的 CDN 的優(yōu)點(diǎn)芝薇,但有一點(diǎn)我們要注意的胚嘲,如果我們?cè)诒镜剡\(yùn)行使用“協(xié)議省略”的 URL 可能不會(huì)得到如預(yù)期運(yùn)行效果,由于我們?cè)诒镜剡\(yùn)行頁(yè)面“協(xié)議省略”使用的基礎(chǔ)協(xié)議是 file洛二,而不是 http 或 https馋劈,所以一般來(lái)說(shuō)我們?cè)诒镜刂苯舆\(yùn)行頁(yè)面是無(wú)法正確獲取到 CDN 的內(nèi)容攻锰,我們可以把頁(yè)面放到本地Web服務(wù)器中運(yùn)行,如 Apache 或IIS中妓雾,然后運(yùn)行 http://localhost的地址就可以加載成功了娶吞。
參考
http://www.hanselman.com/blog/CDNsFailButYourScriptsDontHaveToFallbackFromCDNToLocalJQuery.aspx
http://encosia.com/cripple-the-google-cdns-caching-with-a-single-character/
https://developers.google.com/speed/libraries/devguide

原著:JK_Rush 原文鏈接:引用CDN內(nèi)容的方法總結(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市械姻,隨后出現(xiàn)的幾起案子妒蛇,更是在濱河造成了極大的恐慌,老刑警劉巖楷拳,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绣夺,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡唯竹,警方通過(guò)查閱死者的電腦和手機(jī)乐导,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)浸颓,“玉大人物臂,你說(shuō)我怎么就攤上這事〔希” “怎么了棵磷?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)晋涣。 經(jīng)常有香客問(wèn)我仪媒,道長(zhǎng),這世上最難降的妖魔是什么谢鹊? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任算吩,我火速辦了婚禮,結(jié)果婚禮上佃扼,老公的妹妹穿的比我還像新娘偎巢。我一直安慰自己,他們只是感情好兼耀,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布压昼。 她就那樣靜靜地躺著,像睡著了一般瘤运。 火紅的嫁衣襯著肌膚如雪窍霞。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天拯坟,我揣著相機(jī)與錄音但金,去河邊找鬼。 笑死郁季,一個(gè)胖子當(dāng)著我的面吹牛傲绣,可吹牛的內(nèi)容都是我干的掠哥。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼秃诵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了塞琼?” 一聲冷哼從身側(cè)響起菠净,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎彪杉,沒(méi)想到半個(gè)月后毅往,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡派近,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年攀唯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渴丸。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡侯嘀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出谱轨,到底是詐尸還是另有隱情戒幔,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布土童,位于F島的核電站诗茎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏献汗。R本人自食惡果不足惜敢订,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望罢吃。 院中可真熱鬧楚午,春花似錦、人聲如沸刃麸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)泊业。三九已至把沼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吁伺,已是汗流浹背饮睬。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留篮奄,地道東北人捆愁。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓割去,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親昼丑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子呻逆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • <a name='html'>HTML</a> Doctype作用?標(biāo)準(zhǔn)模式與兼容模式各有什么區(qū)別? (1)菩帝、<...
    clark124閱讀 3,456評(píng)論 1 19
  • @轉(zhuǎn)自GitHub 介紹js的基本數(shù)據(jù)類型咖城。Undefined、Null呼奢、Boolean宜雀、Number、Strin...
    YT_Zou閱讀 1,143評(píng)論 0 0
  • 在線閱讀 http://interview.poetries.top[http://interview.poetr...
    程序員poetry閱讀 114,255評(píng)論 24 450
  • 滑塊視圖容器常用屬性: swiper.js添加代碼: swiper.wxss添加代碼: 來(lái)源:http://bbs...
    小碼哥教育520it閱讀 9,443評(píng)論 1 1
  • 我喜歡夜握础。 夜沉寂而深邃辐董,讓人在靜靜的孤獨(dú)中不再孤單。那時(shí)禀综,所面對(duì)的简烘,是一個(gè)真實(shí)的自己,脆弱得總要流淚菇存,流淚后更為...
    泠風(fēng)思語(yǔ)閱讀 148評(píng)論 0 1