33

ASP.NET 4.5 有一个很棒的新捆绑功能,并且似乎支持使用 CDN。Microsoft 给出的将捆绑功能与 CDN 结合使用的示例是这样的

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.
} 

这似乎表明您需要明确告诉它 CDN 上文件的路径。

CloudFront CDN(我想还有很多其他的)为您提供了一个镜像您自己的子域。当你击中http://uniquesubdomain.cloudfront.net/js/myfile.js?v=1它时http://mydomain.com/js/myfile.js?v=1

这样,您可以简单地为所有链接添加前缀,http://uniquesubdomain.cloudfront.net/并且您的文件是来自 CloudFront 的服务器。

ASP.NET 4.5 捆绑功能是否与这种类型的 CDN 兼容?是否有一种内置方法可以将捆绑功能作为其与 CDN 域的所有链接的前缀?

例如。

bundles.UseCdn = true;
var myBundle= new ScriptBundle("~/bundles/js", "https://uniquedomain.cloudfront.net/");
myBundle.Include("~/js/file1.js");
myBundle.Include("~/js/file2.js");

会导致

    <script src="https://uniquedomain.cloudfront.net/bundles/js?v=6y-qVPSK3RYOYHfPhOBDd92H4LjEjs-D3Hh2Yml6CXA1"></script>
4

4 回答 4

9

此功能不是内置的,但可以通过几个小帮助方法实现。这是我现在正在使用的:

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

请注意,我在配置文件的 appSettings 部分中有自己的配置设置,称为 EnableCdn。从 Razor 视图调用时,这会产生正确的输出,将 CDN 域附加到路径上。

在您的 Razor 文件中,只需执行 Cdn.RenderScripts("~/pathtoscriptbundle")

于 2013-05-31T16:48:23.277 回答
1

另一种选择是像这样使用 Scripts 或 Styles RenderFormat 方法。这对我来说特别有用,因为我偶尔自定义 tagFormat 以将引用包装在条件 html 注释中,或者附加其他属性,如 media="screen,print"。代码更简单,因为您可以在字符串变成 HTML 编码字符串之前对字符串执行尴尬的替换。

或者,您可以将 tagFormat 作为默认值是下面提到的字符串常量的那些方法的可选参数。

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);
    }
}
于 2013-08-29T00:16:39.763 回答
1

可能不是您正在寻找的内容,但许多 CDN 现在使用 DNS 充当反向代理,因此您不必明确链接您的资产。我知道 Cloudflare 会这样做,我相信其他人也会这样做。

于 2013-04-23T17:51:31.767 回答
0

这是不可能的,但是您可以使用文本模板将 JS 文件组合为一个 js 并将其放在 CDN 上,而不是使用 bundle。

<#@ ... hostspecific="true"  extension=".js">

<#

    Write (System.IO.File.ReadAllText("a.js"));
    Write (System.IO.File.ReadAllText("b.js"));
 #>
于 2013-04-26T04:57:51.783 回答