2013-01-18 77 views
1

我在MVC4中嘗試捆綁和縮小,遇到了一個有趣的問題。 我正在使用Coffeescript,我想要一個像@Scripts.Render()方法那樣工作的渲染助手。捆綁助手捆綁和拆分咖啡腳本

例如,假設我有這樣的捆綁配置:

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

在CSHTML,當我做@Scripts.Render()我得到基於web.config中的調試設置不同的結果。如果調試是真的,我得到每個文件一個腳本標記,否則我得到一個腳本標記,返回捆綁和縮小的js。這可以。

讓我們現在假設我想對我的咖啡文本做同樣的事情。我創建這樣的捆綁產品:

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(),但它使用了System.Web.Optimization程序集內部的AssetManager類。

我在想如果你有一個關於如何以一種乾淨的方式做到這一點的想法(即:使用可用的公共類,而不是複製和粘貼整個AssetManager代碼,在創建捆綁時不做花哨的Directory.EnumerateFiles) 。

謝謝!我知道一個更快的解決方案是使用Mindscape Workbench並捆綁生成的js文件,我正在尋找使用框架的東西,也許還要避免告訴團隊安裝一個工具人們可能不喜歡...

回答

1

最後,我去了一個HtmlHelper解決方案。仍處於早期階段,但按我的意願工作。詳情請見blog post

以下是完整的助手代碼的情況下,博客的那張丟失......

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

對不起,我沒有解決你的確切問題,但我確實想在帖子結尾與你的PS說話。

在這個時候,我並不認爲我們有一個「沒有工具」的故事,但我同意「使用框架」的觀點。

爲此,我強烈建議使用TypeScript。你不需要學習一門新的語言(就像你使用CoffeeScript一樣),但是它給了你一個強類型的JavaScript版本,你可以使用更多的類似c#(以及類型驗證等)。

它會帶你20分鐘要經過一些教程:

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

或者,更好,看看從上倒下的BUILD會議:

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

Btw ...如果這不是你想要去的方向,不用擔心...我只是發現很多開發者甚至不知道TypeScript還是一個選項。

希望這可以幫助您爲您的團隊簡化事情。

乾杯。

+0

雖然打字稿有趣的是,它帶來了幾乎同樣的問題在這裏。你需要在VS中有一個插件(並且Express版本中不支持插件),並且你需要一種方法將你的.ts文件編譯成javascript,就像每個coffeescript文件一樣。 – Tallmaris

+0

嘿,別擔心!這不適合所有人,我其實並沒有看到你在OP中使用Express,這絕對是一個限制因素。儘管如此,我發現它與我們在c#和VS工作流中已經知道的更接近,在其他情況下它可能適用於您。希望你的新方向適合你的團隊! – MisterJames