在静态资产和基于CDN的资产之间切换以进行开发和部署的最佳方法

时间:2012-02-20 17:04:00

标签: c# asp.net .net asp.net-mvc asp.net-mvc-3

我正在ASP.NET MVC3中开发和应用。我计划利用亚马逊Cloudfront产品作为CDN来提供静态资产。

我很好奇是否有人设计了一种简单的方法来切换用于开发的本地资产和用于部署的基于CDN的资产?

非常感谢任何提示或技巧。

5 个答案:

答案 0 :(得分:7)

与保罗的答案相似。

过去我使用了UrlHelper的扩展方法,该方法根据web.config中的值创建了链接。

这很有用,因此您不必在发布后对视图进行微观处理,就像在发布时更新web.config条目一样简单。任何需要使用CDN资源的资源,只需说Url.CdnContent("~/site.css")

即可

我现在不在我的开发电脑上,但是当我回到家时,我会告诉你扩展方法的来源

这非常简单,但它适用于我需要做的事情

public static string CdnContent(this UrlHelper helper, string relativePath)
{
    var cdnRoot = ConfigurationManager.AppSettings["cygnus.cdnroot"];
    if (string.IsNullOrEmpty(cdnRoot))
        return UrlHelper.GenerateContentUrl(relativePath, helper.RequestContext.HttpContext);

    if (relativePath.StartsWith("~"))
        relativePath = relativePath.Substring(1);

    if (cdnRoot.EndsWith("/"))
        cdnRoot = cdnRoot.Substring(0, cdnRoot.Length - 1);

    if (!relativePath.StartsWith("/"))
        relativePath = "/" + relativePath;

    return cdnRoot + relativePath;
}

答案 1 :(得分:4)

我过去使用一些简单的规则来完成它:

  • 始终在CSS中使用文件相对路径
  • 始终使用标准模式引用视图中的内容(我使用Url.Content的应用程序相对路径,即Url.Content("~/content/file.jpg")
  • 不要在JavaScript中引用文件。

然后在我的部署过程中,我可以简单地将所有静态资产从站点复制到CDN,CSS将起作用,因为它的相对(CSS url()值始终相对于它们所在的CSS文件,而不是请求),我将使用正则表达式替换我希望具有CDN基本路径的形式的视图中的任何字符串。

答案 2 :(得分:2)

好问题。我建议你使用条件编译变量

如果您的项目处于调试模式,则会链接本地资产。如果您的项目处于发布模式,则会链接CDN资产。

以下是一个示例:

<head runat="server">
    <% #if DEBUG %>
        <link rel="stylesheet" type="text/css" href="/Assets/Styles/Default.css" />
    <% #else %>
        <link rel="stylesheet" type="text/css" href="http://cdn.mysite.com/Assets/Styles/Default.css" />
    <% #endif %>
</head>

但请注意,当您发布项目时,它应该处于发布模式。有一次,我更新了我的一个项目,它处于DEBUG模式,一切都出错了。

以下是有关条件编译的一些不错的链接:

http://haacked.com/archive/2007/09/16/conditional-compilation-constants-and-asp.net.aspx

http://odetocode.com/blogs/scott/archive/2005/12/01/conditional-compilation-in-asp-net-2-0.aspx

http://odetocode.com/blogs/scott/archive/2007/09/24/more-on-conditional-compilation-in-asp-net.aspx

答案 3 :(得分:1)

我使用了一组扩展方法(见下文)。您可以使用它们作为基础/示例来创建自己的自定义调试/发布扩展方法。

一般调试/发布:

public static MvcHtmlString DebugReleaseString(this System.Web.Mvc.HtmlHelper html, string debugString, string releaseString)
{
    string toReturn = debugString;
#if !DEBUG
    if (!string.IsNullOrEmpty(releaseString))
        toReturn = releaseString;
#endif
    return MvcHtmlString.Create(toReturn);
}

一般调试/发布用法:

@Html.DebugReleaseString("/images/myimage.jpg", "http://mycdn.com/images/myimage.jpg")

调试/发布CSS标签:

public static MvcHtmlString CssTag(this System.Web.Mvc.HtmlHelper html, string fileName)
{
    return html.CssTag(fileName, string.Empty);
}

public static MvcHtmlString CssTag(this System.Web.Mvc.HtmlHelper html, string fileName, string releaseFileName)
{
    if (string.IsNullOrEmpty(fileName))
        throw new ArgumentNullException("fileName");

    string cssTag = string.Format(
        "<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\" />",
        html.MeDebugReleaseString(fileName, releaseFileName));

    return MvcHtmlString.Create(cssTag);
}

调试/发布CSS标记用法:

@Html.CssTag("/styles/mystyle.css")
@Html.CssTag("/styles/mystyle.css", "http://mycdn.com/styles/mystyle.css")

调试/发布JS标签:

public static MvcHtmlString JavascriptTag(this System.Web.Mvc.HtmlHelper html, string fileName)
{
    return html.JavascriptTag(fileName, string.Empty);
}

public static MvcHtmlString JavascriptTag(this System.Web.Mvc.HtmlHelper html, string fileName, string releaseFileName)
{
    if (string.IsNullOrEmpty(fileName))
        throw new ArgumentNullException("fileName");

    string jsTag = string.Format("<script type=\"text/javascript\" src=\"{0}\"></script>",
                                 html.MeDebugReleaseString(fileName, releaseFileName));

    return MvcHtmlString.Create(jsTag);
}

调试/发布JS标记用法:

@Html.JavascriptTag("/scripts/myscript.css")
@Html.JavascriptTag("/scripts/myscript.css", "http://mycdn.com/scripts/myscript.js")

其他调试/发布选项:

public enum RenderModeEnum
{
    Debug,
    Release,
    DebugAndRelease
}

public static MvcHtmlString CssTag(this System.Web.Mvc.HtmlHelper html, string fileName, RenderModeEnum tagRenderMode)
{
    if (tagRenderMode == RenderModeEnum.DebugAndRelease)
        return html.CssTag(fileName);

#if DEBUG
    if (tagRenderMode == RenderModeEnum.Debug)
        return html.CssTag(fileName);
#else
    if (tagRenderMode == RenderModeEnum.Release)
        return html.CssTag(fileName);
#endif

    return MvcHtmlString.Empty;
}

public static MvcHtmlString JavascriptTag(this System.Web.Mvc.HtmlHelper html, string fileName, RenderModeEnum tagRenderMode)
{
    if (tagRenderMode == RenderModeEnum.DebugAndRelease)
        return html.JavascriptTag(fileName);

#if DEBUG
    if (tagRenderMode == RenderModeEnum.Debug)
        return html.JavascriptTag(fileName);
#else
    if (tagRenderMode == RenderModeEnum.Release)
        return html.JavascriptTag(fileName);
#endif

    return MvcHtmlString.Empty;
}

其他调试/发布选项用法:

@Html.CssTag("/styles/mystyle.css", RenderModeEnum.DebugAndRelease)
@Html.CssTag("/styles/mystyle.css", RenderModeEnum.Debug)
@Html.CssTag("http://mycdn.com/styles/mystyle.css", RenderModeEnum.Release)

答案 4 :(得分:1)

我专门开发了一个解决这个问题的库。

https://github.com/vincpa/mvc.resourceloader