11

讓我們假設我們的應用程序處於脫機狀態,即我們不能使用第三方CDN,因此我們正在創建自己的應用程序。 我想將所有供應商腳本託管在單獨的(父級)Web應用程序中,然後將它們包含在其他幾個MVC應用程序的捆綁包中。從多個CDN位置創建腳本包

例如

  • http://localhost/parentWeb/Scripts/jquery.js
  • http://localhost/parentWeb/Scripts/jquery-ui.js
  • http://localhost/parentWeb/Scripts/globalize.js

我想在位於ASP.NET MVC應用程序的網站,包括:http://localhost/parentWeb/childWeb

即做這樣的事情:

bundles.UseCdn = true; 
bundles.Add(
    new ScriptBundle(
     "~/bundles/VendorScripts", 
     "http://localhost/parentWeb/Scripts/jquery.js", 
     "http://localhost/parentWeb/Scripts/jquery-ui.js", 
     "http://localhost/parentWeb/Scripts/globalize.js")); 

......當然這當然是不可能的。有沒有很好的解決方法?

回答

6

我發現了一個與CDN無關的解決方案。基本上,授予childWebparentWeb的子目錄託管,在childWeb應用以下束配置主從parentWeb文件並將它們捆綁照常:

bundles.Add(
    new ScriptBundle(
     "~/bundles/VendorScripts").Include(
     "~/../Scripts/jquery.js", 
     "~/../Scripts/Scripts/jquery-ui.js", 
     "~/../Scripts/globalize.js")); 

重要比特是:~/../,這需要你從根位置上升一級。

+0

所以與您的解決方案在哪裏存儲cdn路徑在該代碼我有同樣的問題,我需要還加載多個CSS使用cdn的捆綁,所以請你可以讓我知道該怎麼做? – coderwill

13

您不能捆綁外部資源。如果你仔細想想,爲什麼你不能。這將需要捆綁器實際下載資源並將其保存到文件系統,然後才能使用該資源,當然,如果無法訪問外部資源,則會使用某種後備方法異步執行。然後,它將不得不在上每頁加載,因爲它無法檢查lastmod(因此知道它是否實際需要重新綁定),而無需首先獲取資源。

如果您使用CDN資源,打包程序僅僅將URL直接打印到頁面;它不做任何修改。即使這樣,它也只允許你爲這一個URL創建一個「捆綁」,因爲1)捆綁多個CDN資源是沒有意義的,因爲這會破壞CDN的目的,並且2)該捆綁僅存在於這個如果CDN資源不可用,則提供後備方案。否則,只需將它硬編碼到頁面上,而不用擔心設置捆綁軟件。

+1

雖然您無法打包外部資源(您的觀點非常正確),但ScriptBundle實際上支持CDN。這個博客文章解釋了一切很好http://www.hanselman.com/blog/CDNsFailButYourScriptsDontHaveToFallbackFromCDNToLocalJQuery.aspx –

+1

@BryanRayner:不知道什麼是衝突。我從來沒有說捆綁沒有CDN支持。恰恰相反,實際上,正如我提到使用帶有腳本包的CDN。但是,就像我在上面的回答中所說的那樣,捆綁器實際上並不*使用CDN資源做任何事情。它只是將頁面上的靜態腳本標記放到CDN文件中。它不會將其與其他腳本或CSS文件縮小/組合。 –

+0

重新閱讀您的問題,我必須同意 - 您從未說過捆綁軟件沒有CDN支持。當我最初閱讀您的答案時,「您不能捆綁外部資源」似乎表明ScriptBundles不能用於爲客戶端提供外部資源。 –

1

要爲CDN資源使用ScriptBundles,您需要使用重載的構造函數。不幸的是,你需要爲每個文件指定多個ScriptBundle

這是一個偉大的博客文章,解釋事情: http://www.hanselman.com/blog/CDNsFailButYourScriptsDontHaveToFallbackFromCDNToLocalJQuery.aspx

而這裏的一個代碼片段:

bundles.UseCdn = true; 
var bundle = new ScriptBundle("~/bundles/bundleNameHere", "//cdn.host.path/to/file"); 
// Path to the version of the file on your server (in case the CDN fails) 
bundle.Include("~/../Scripts/path/to/file"); 
// JS expression to run, to test if CDN delivered the file or not 
bundle.CdnFallbackExpression = "window.ValueYouExpectToBeTruthy"; 

bundles.Add(bundle); 
6

我知道這是一個老話題,但我來到這裏尋找一種實際的方式捆綁CDN資源。從@Chris Pratt的回答中,我明白這是不可能的。

如果您想知道,我正在根據Google's Web Performance Best Practises優化現有項目,當有多個腳本標記時,得分較低,而當所有腳本都綁定到一個腳本參考中時,得分較高。

我需要一種方法來按順序捆綁所有CDN腳本資源以及本地資源。我在這個github repo上工作,解決了我的問題。

有了它,你可以建立一個捆綁包列表,每個捆綁包都包含對cdn資源的引用,保存到本地的資源,以及一個布爾值,指示是否要將該捆綁包縮小。

List<Bundle> jsBundles = new List<Bundle>(); 
jsBundles.Add(new Bundle("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js", @"~/jquery.min.js", Bundle.BundleType.JavaScript, false)); 
jsBundles.Add(new Bundle("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.0/jquery-ui.min.js", @"~/jquery-ui.min.js", Bundle.BundleType.JavaScript, false)); 
jsBundles.Add(new Bundle(@"~/my-local-script.js", Bundle.BundleType.JavaScript, true)); 

要放置在頁面上,你可以使用

@jsBundles.Load(); 

這將處理列表中的所有包,下載內容對於尚未在過去24小時內被下載包(它更新每24小時或Web應用程序重新啓動時)。下載的所有內容將被放置在本地文件(如有指定)

所有內容將被合併到最終結果中,該結果將被拖放到腳本標記(或CSS的鏈接標記)的頁面中。

Load函數還接受最終腳本/ css內容的本地文件URL。如果指定,則會給出帶有src的標記給該本地文件的相對路徑。例如。

@jsBundles.Load("~/js/all-my-scripts.js"); 

上面的語句將返回類似:

<script src="~/js/all-my-scripts.js"></script> 

異步屬性可以被添加到腳本標籤如果提供的加載函數的第二個參數。

它也適用於css cdn資源。例如。

List<Bundle> cssBundles = new List<Bundle>(); 
cssBundles.Add(new Bundle("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.0/jquery-ui.min.css", @"~/jquery.ui.css", Bundle.BundleType.CSS, false)); 
cssBundles.Add(new Bundle(@"~/css/my-local-style.css", Bundle.BundleType.CSS, true)); 


@cssBundles.Load("~/css/all-my-styles.css"); 

這是爲了那些喜歡我的人,來到這裏尋找一種實際捆綁CDN資源的方式。

+0

聰明的解決方案,但是這不會破壞使用CDN的目的嗎?Web客戶端必須從您的服務器下載完整的捆綁CDN腳本,因爲它們不會將其放入緩存中。使用真正的CDN腳本鏈接,問題在於,由於許多其他站點鏈接到相同的CDN URL,因此您的Web客戶端已經緩存了腳本文件的可能性很高。 –