2013-02-12 12 views
9

Utilizzando il built-in MVC4 bundler, come faccio a anteporre il mio URL CDN ai tag di collegamento che produce? Ho installato Amazon Cloudfront in modo che raccolga risorse dal mio server web quando richiesto per la prima volta. Così, quando ho definisco un bundle in questo modo:Prepend conto dell'URL CDN sull'output del bundle di mvc 4

bundles.Add(new StyleBundle("~/Content/css").Include(
    "~/Content/reset.css", 
    "~/Content/960_24_col.css", 
    "~/Content/Site.css" 
)); 

Se distribuito, mi può fare riferimento così:

http://[cloundfrontid].cloudfront.net/Content/css?v=muhFMZ4thy_XV3dMI2kPt-8Rljm5PNW0tHeDkvenT0g1 

Ora ho solo bisogno di cambiare i collegamenti prodotti dalla Bundler dall'essere relativamente ai collegamenti assoluti indicando il mio CDN.

<link href="[INSERT_CDN_URL_HERE]/Content/css?v=muhFMZ4thy_XV3dMI2kPt-8Rljm5PNW0tHeDkvenT0g1" rel="stylesheet"/> 

Penso che possa essere possibile riscrivere il percorso utilizzando IBundleTransform ma non riesco a trovare alcun esempio di questo.

NOTA: Giusto per essere chiari, so che è possibile specificare un collegamento CDN per un pacchetto, ma che funziona solo se il pacchetto può essere sostituito da un collegamento statico.

+0

Perché non è possibile utilizzare un collegamento statico al CDN? –

+0

perché non so quale sarà il collegamento in fase di compilazione. Il bundler lo assegna dinamicamente con una stringa di busting della cache, ad es./Content/css? V = muhFMZ4thy_XV3dMI2kPt-8Rljm5PNW0tHeDkvenT0g1 – PeteG

+0

Il tuo CDN sta effettivamente utilizzando la stringa di query per attivare il contenuto restituito? Non potresti semplicemente codificare esplicitamente le versioni nel tuo CDN? Ad esempio/content/css1 e lo colpisci ogni volta che giri i tuoi bundle? –

risposta

6

ho appena messa a punto MaxCDN e corse in stesso problema esatto.

Come sapete, la proprietà bundles.UseCdn non è l'ideale perché non vogliamo dover specificare l'URL esatto per il pacchetto. Un CDN come Max CDN è lo stesso url esatto, stringa di query e tutto, tranne un sottodominio diverso.

Ecco come ho finito per risolverlo.

Ho creato una classe BundleHelper che avvolgerà il metodo di rendering e quindi anteporrà il percorso con il sottodominio CDN.

Ecco ciò che la classe si presenta come:

namespace MyDomain.Web.Helpers 
{ 
    public class BundleHelper 
    { 
     public static string CdnPath = "http://cdn.mydomain.com"; 

     public static IHtmlString RenderScript(string path) 
     { 
      var opt = System.Web.Optimization.Scripts.Render(path); 
      string htmlString = HttpUtility.HtmlDecode(opt.ToHtmlString()); 

      if (BundleTable.EnableOptimizations) 
      { 
       htmlString = htmlString.Replace("<script src=\"/", String.Format("<script src=\"{0}/", CdnPath)); 
      } 

      return new HtmlString(htmlString); 
     } 

     public static IHtmlString RenderStyle(string path) 
     { 
      var opt = System.Web.Optimization.Styles.Render(path); 
      string htmlString = HttpUtility.HtmlDecode(opt.ToHtmlString()); 

      if (BundleTable.EnableOptimizations) 
      { 
       htmlString = htmlString.Replace("<link href=\"/", String.Format("<link href=\"{0}/", CdnPath)); 
      } 

      return new HtmlString(htmlString); 
     } 
    } 
} 

Poi da utilizzare nelle viste, faccio semplicemente:

@BundleHelper.RenderStyle("~/Content/css") 
@BundleHelper.RenderStyle("~/Content/themes/base/css") 

@BundleHelper.RenderScript("~/bundles/jquery") 
@BundleHelper.RenderScript("~/bundles/jqueryui") 

Spero che questo aiuti.

+1

Mi aiuta molto. –

+1

Non l'ho provato ma questa sembra una buona soluzione. Alla fine sono andato con la soluzione descritta [sul mio blog] (http://www.peteg.eu/blog/2013/03/15/using-mvc4-bundler-with-a-content-delivery-network/) . Contrassegnerò il tuo come accettato perché è più efficiente. – PeteG

+0

Ciao BigJoe: voglio anche anteporre cdn url all'output di bundler..e ho fatto lo stesso come hai descritto, non ho capito cosa hai fatto in ViewPages. Puoi spiegare per favore? – Ankita

1

Si prega di dare un'occhiata @Using a CDN ricerca per "Uso di una CDN"

Come detto da Di Rick Anderson nel asp.net/mvc,

Il codice follow sostituisce il jQuery locale fascio con una Pacchetto CDN jQuery .

public static void RegisterBundles(BundleCollection bundles) 
    { 
    //bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
    //   "~/Scripts/jquery-{version}.js")); 

    bundles.UseCdn = true; //enable CDN support 

    //add link to jquery on the CDN 
    var jqueryCdnPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js"; 

    bundles.Add(new ScriptBundle("~/bundles/jquery", 
       jqueryCdnPath).Include(
       "~/Scripts/jquery-{version}.js")); 

    // Code removed for clarity. 
    } 

Nel codice di cui sopra, jQuery sarà richiesto dal CDN, mentre in modalità di rilascio e la versione di debug di jQuery sarà recuperato a livello locale in modalità debug. Quando si utilizza un CDN, è necessario disporre di un meccanismo di fallback nel caso in cui la richiesta CDN non riesca. Il seguente frammento di markup dalla fine del file di layout mostra lo script aggiunto alla richiesta jQuery nel caso in cui la CDN non riesca.

</footer> 

     @Scripts.Render("~/bundles/jquery") 

     <script type="text/javascript"> 
      if (typeof jQuery == 'undefined') { 
       var e = document.createElement('script'); 
       e.src = '@Url.Content("~/Scripts/jquery-1.7.1.js")'; 
       e.type = 'text/javascript'; 
       document.getElementsByTagName("head")[0].appendChild(e); 

      } 
     </script> 

     @RenderSection("scripts", required: false) 
    </body> 
</html> 

Nel aver incollato il tratto da Asp.net/MVC, nel caso in cui vi sia utile poi Cheers to Rick Anderson per il suo posto ...

+0

Ooops its a Feb, 12 post :) – Shubh