c# - mvc - scriptbundle
Usando ASP.NET 4.5 Bundling y un CDN(por ejemplo, CloudFront) (4)
Esta funcionalidad no está incorporada, pero es posible con un par de pequeños métodos de ayuda. Esto es lo que estoy usando en este momento:
public static class Cdn
{
private const string CdnRoot = "//cloudfrontdomainhere.com";
private static bool EnableCdn
{
get
{
bool enableCdn = false;
bool.TryParse(WebConfigurationManager.AppSettings["EnableCdn"], out enableCdn);
return enableCdn;
}
}
public static IHtmlString RenderScripts(string bundlePath)
{
if (EnableCdn)
{
string sourceUrl = CdnRoot + Scripts.Url(bundlePath);
return new HtmlString(string.Format("<script src=/"{0}/"></script>", sourceUrl));
}
return Scripts.Render(bundlePath);
}
public static IHtmlString RenderStyles(string bundlePath)
{
if (EnableCdn)
{
string sourceUrl = CdnRoot + Styles.Url(bundlePath);
return new HtmlString(string.Format("<link href=/"{0}/" rel=/"stylesheet/" />", sourceUrl));
}
return Styles.Render(bundlePath);
}
}
Tenga en cuenta que tengo mi propia configuración llamada EnableCdn en la sección appSettings de mi archivo de configuración. Cuando se llama desde una vista Razor, esto produce la salida correcta, que agrega el dominio CDN a las rutas.
En sus archivos Razor simplemente haga Cdn.RenderScripts ("~ / pathtoscriptbundle")
ASP.NET 4.5 tiene una excelente nueva función de agrupación y parece tener cierto soporte para el uso de CDN. El ejemplo dado por Microsoft para el uso de la función de agrupación con un CDN es esto
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.
}
Lo que parece sugerir que necesita decirle explícitamente la ruta a su archivo en el CDN.
CloudFront CDN (y supongo que muchos otros) le da un subdominio que refleja el suyo. Cuando accedes a http://uniquesubdomain.cloudfront.net/js/myfile.js?v=1
se muestra http://mydomain.com/js/myfile.js?v=1
De esta manera, puede simplemente ponerle un prefijo a todos sus enlaces con http://uniquesubdomain.cloudfront.net/
y sus archivos son servidores de CloudFront.
¿Es compatible la función de empaquetado ASP.NET 4.5 con este tipo de CDN? ¿Existe una forma incorporada para que la función de agrupamiento prefija todos sus enlaces con su dominio CDN?
P.ej.
bundles.UseCdn = true;
var myBundle= new ScriptBundle("~/bundles/js", "https://uniquedomain.cloudfront.net/");
myBundle.Include("~/js/file1.js");
myBundle.Include("~/js/file2.js");
causaría
<script src="https://uniquedomain.cloudfront.net/bundles/js?v=6y-qVPSK3RYOYHfPhOBDd92H4LjEjs-D3Hh2Yml6CXA1"></script>
No es posible, pero en lugar de paquete, puede usar una plantilla de texto para combinar archivos JS como un js y ponerlos en CDN.
<#@ ... hostspecific="true" extension=".js">
<#
Write (System.IO.File.ReadAllText("a.js"));
Write (System.IO.File.ReadAllText("b.js"));
#>
Otra opción es usar el método Scripts o Styles RenderFormat como tal. Esto fue particularmente útil para mí, ya que personalizo el tagFormat ocasionalmente para envolver referencias en comentarios html condicional, o anexar atributos adicionales como media = "screen, print". El código es más simple porque puede hacer el incómodo Reemplazar en una cadena, antes de que se convierta en una cadena codificada en HTML.
Alternativamente, podría tener tagFormat como un parámetro opcional para aquellos métodos donde el valor predeterminado son las constantes de cadena mencionadas a continuación.
public class BundleHelper
{
public static readonly string StyleTagFormat = "<link href=/"{0}/" rel=/"stylesheet/"/>";
public static readonly string ScriptTagFormat = "<script src=/"{0}/"></script>"
/// <summary>
/// Customised script bundle rendering method with CDN support if optimizations and CDN enabled.
/// </summary>
public static IHtmlString RenderScriptFormat(string tagFormat, string path)
{
// Check for absolute url to ensure the standard framework support for CDN bundles, with a CdnPath still works.
if (AppSettings.Bundling.EnableCdn && !UriHelper.IsAbsoluteUrl(Scripts.Url(path).ToString()))
{
tagFormat = tagFormat.Replace(" src=/"{0}/"", String.Format(" src=/"{0}{{0}}/"", AppSettings.Bundling.BundlesCDNPrefixUrl));
}
return Scripts.RenderFormat(tagFormat, path);
}
/// <summary>
/// Customised styles bundle rendering method with CDN support if optimizations and CDN enabled.
/// </summary>
public static IHtmlString RenderStyleFormat(string tagFormat, string path)
{
// Check for absolute url to ensure the standard framework support for CDN bundles, with a CdnPath still works.
if (AppSettings.Bundling.EnableCdn && !UriHelper.IsAbsoluteUrl(Styles.Url(path).ToString()))
{
tagFormat = tagFormat.Replace(" href=/"{0}/"", String.Format(" href=/"{0}{{0}}/"", AppSettings.Bundling.BundlesCDNPrefixUrl));
}
return Styles.RenderFormat(tagFormat, path);
}
}
public class UriHelper
{
/// <summary>
/// Determines whether a url is absolute or not.
/// </summary>
/// <param name="url">Url string to test.</param>
/// <returns>true/false.</returns>
/// <remarks>
/// Examples:
/// ?IsAbsoluteUrl("hello")
/// false
/// ?IsAbsoluteUrl("/hello")
/// false
/// ?IsAbsoluteUrl("ftp//hello")
/// false
/// ?IsAbsoluteUrl("//hello")
/// true
/// ?IsAbsoluteUrl("ftp://hello")
/// true
/// ?IsAbsoluteUrl("http://hello")
/// true
/// ?IsAbsoluteUrl("https://hello")
/// true
/// </remarks>
public static bool IsAbsoluteUrl(string url)
{
Uri result;
return Uri.TryCreate(url, UriKind.Absolute, out result);
}
}
Puede que no sea exactamente lo que estás buscando, pero ahora muchas de las CDN actúan como un proxy inverso usando DNS, por lo que no tienes que vincular tus activos explícitamente. Sé que Cloudflare hace esto y estoy seguro de que otros también lo hacen.