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

发布于 2025-01-07 08:44:43 字数 155 浏览 1 评论 0原文

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

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

任何提示或技巧将不胜感激。

I am developing and application in ASP.NET MVC3. I am planning to take advantage of Amazons Cloudfront offering as a CDN to serve static assets.

I am curious if anyone has devised a simple method for switching between local assets for development and CDN based assets for deployment?

Any tips or tricks would be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

北渚 2025-01-14 08:44:43

与保罗的回答类似。

过去,我使用了 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;
}

Similarly to Paul's answer.

In the past I've used an extension method for UrlHelper that created the links based on a value from the web.config.

This is helpful so you don't have to minipulate your views after publishing, and it's as simple as updating a web.config entry on publish. Any resources that require using the CDN resource, you simply say Url.CdnContent("~/site.css")

I'm not on my development pc at the moment, but when I get home, I'll get you the source for my extension method

It's very simplistic, but it works for what I need it to do

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;
}
尹雨沫 2025-01-14 08:44:43

我过去使用一些简单的规则做到了这一点:

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

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

I've done it in the past using a few simple rules:

  • Always use file relative paths in CSS
  • Always use a standard pattern to reference content in your views (I use application relative paths with Url.Content, ie. Url.Content("~/content/file.jpg"))
  • Do not reference files in JavaScript.

Then in my deploy process I can simply copy all static assets from the site to the CDN, the CSS will just work since its relative (CSS url() values are always relative to the CSS file they are in, not the request), and I will use regex to replace any strings in my views that are in the form I expect to have the CDN base path.

撑一把青伞 2025-01-14 08:44:43

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

如果您的项目处于调试模式,则会链接本地资源。如果您的项目处于发布模式,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>

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

以下是一些关于条件编译的好链接:

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

Nice question. I suggest you use Conditional Compilation Variables.

If your project is in debug mode, local assets would be linked. If your project is in release mode, CDN assets would be linked.

Here is a sample:

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

But be careful, when you publish you project, it should be in release mode. Once, I updated one of my projects and it was in DEBUG mode and everything went wrong.

Here are some nice links about Conditional Compilation:

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

穿越时光隧道 2025-01-14 08:44:43

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

常规调试/发布:

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)

I have a set of extension methods I use (see below). You can use these as a base/example to create your own custom debug/release extension methods.

General debug/release:

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

General debug/release usage:

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

Debug/release CSS tags:

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

Debug/release CSS tags usage:

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

Debug/release JS tags:

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

Debug/release JS tags usage:

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

Additional debug/release options:

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

Additional debug/release options usage:

@Html.CssTag("/styles/mystyle.css", RenderModeEnum.DebugAndRelease)
@Html.CssTag("/styles/mystyle.css", RenderModeEnum.Debug)
@Html.CssTag("http://mycdn.com/styles/mystyle.css", RenderModeEnum.Release)
孤芳又自赏 2025-01-14 08:44:43

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

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

I've developed a library specifically to tackle this problem.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文