1

我在 MVC4 中尝试使用 Bundle 和 Minification 并遇到了一个有趣的问题。我正在使用 Coffeescript,我想要一个与该@Scripts.Render()方法有点相似的渲染助手。

例如,假设我有这个捆绑配置:

new ScriptBundle("~/bundle/appfiles").Include(
    "~/Scripts/app/sample.js",
    "~/Scripts/app/myApp.js");

在 cshtml 中,当我这样做时,@Scripts.Render()我会根据 web.config 中的调试设置得到不同的结果。如果调试为真,我会为每个文件获得一个脚本标签,否则我会获得一个脚本标签,该标签会返回捆绑和缩小的 js。这可以。

现在让我们假设我想对我的 Coffeescripts 做同样的事情。我创建一个这样的包:

new Bundle("~/bundle/appfiles", new CoffeeBundler(), new JsMinify()).Include(
    "~/Scripts/app/sample.coffee",
    "~/Scripts/app/myApp.coffee");

现在的问题是,如果我使用@Scripts.Render()我在调试时得到每个文件一个脚本,但这根本没有转换。我能做的唯一用途是:

<script type="text/javascript" src="@(BundleTable.Bundles.ResolveBundleUrl("~/bundle/appfiles"))"></script>

但是,即使在调试模式下,这也会将所有内容捆绑在一起然后缩小,这当然不是我想要的。

我试图创建一个Coffee.Render()类似于 Scripts 的帮助器,但它使用 System.Web.Optimization 程序集内部的 AssetManager 类。

我想知道您是否知道如何以干净的方式执行此操作(即:使用可用的公共类,不复制和粘贴整个 AssetManager 代码,在创建捆绑包时不做花哨的 Directory.EnumerateFiles)。

谢谢!

PS:我知道更快的解决方案是使用 Mindscape Workbench 并捆绑生成的 js 文件,我正在寻找使用框架所具有的东西,也许还避免不得不告诉团队安装人们可能不会安装的工具像...

4

2 回答 2

1

最后,我为此选择了 HtmlHelper 解决方案。仍处于早期阶段,但可以按照我的意愿工作。暂时在一篇文中有详细介绍。

这是完整的 Helper 代码,以防博客丢失...

public static class HtmlHelperExtensions
{
    public static MvcHtmlString RenderCoffeeBundle(this HtmlHelper htmlHelper, string virtualPath)
    {
        if (String.IsNullOrEmpty(virtualPath))
            throw new ArgumentException("virtualPath must be defined", "virtualPath");

        var list = GetPathsList(virtualPath);

        //TODO: Nice and cleaner EliminateDuplicatesAndResolveUrls(list);

        var stringBuilder = new StringBuilder();
        foreach (string path in list)
        {
            stringBuilder.Append(RenderScriptTag(path));
            stringBuilder.Append(Environment.NewLine);
        }
        return MvcHtmlString.Create(stringBuilder.ToString());
    }

    private static IEnumerable<string> GetPathsList(string virtualPath)
    {
        var list = new List<string>();

        if (BundleResolver.Current.IsBundleVirtualPath(virtualPath))
        {
            if (!BundleTable.EnableOptimizations)
            {
                foreach (var path in BundleResolver.Current.GetBundleContents(virtualPath))
                {
                    var bundlePath = "~/autoBundle" + ResolveVirtualPath(path.Replace("coffee", "js"));
                    BundleTable.Bundles.Add(new Bundle(bundlePath, new CoffeeBundler()).Include(path));
                    // TODO: Get the actual CustomTransform used in the Bundle
                    // rather than forcing "new CoffeeBundler()" like here
                    list.Add(bundlePath);
                }
            }
            else
                list.Add(BundleResolver.Current.GetBundleUrl(virtualPath));
        }
        else
            list.Add(virtualPath);
        return list.Select(ResolveVirtualPath).ToList();
    }

    private static string RenderScriptTag(string path)
    {
        return "<script src=\"" + HttpUtility.UrlPathEncode(path) + "\"></script>";
    }

    private static string ResolveVirtualPath(string virtualPath)
    {
        return VirtualPathUtility.ToAbsolute(virtualPath);;
    }
}
于 2013-01-19T17:10:26.450 回答
0

抱歉,我没有回答您的确切问题,但我确实想在帖子末尾与您的 PS 交谈。

目前,我真的不认为我们有“没有工具”的故事,但我确实同意“使用框架拥有的东西”的观点。

为此,我强烈建议使用 TypeScript。您不必学习一门新语言(就像使用 CoffeeScript 一样),但它为您提供了一个强类型的 JavaScript 版本,您可以使用它更像 c#(带有类型验证等)。

您将需要 20 分钟来完成一些教程:

http://www.typescriptlang.org/Playground/

或者,更好的是,看看秋季的 BUILD 会议:

http://channel9.msdn.com/Events/Build/2012/3-012

顺便说一句...如果这不是您想要的方向,请不用担心...我只是发现很多开发人员甚至都不知道 TypeScript 作为一种选择。

希望这有助于您为团队简化事情。

干杯。

于 2013-01-18T16:05:07.923 回答