如何使Microsoft Bundle输出JavaScript而不是HTML脚本标记

Idr*_*dra 9 c# asp.net bundle asp.net-mvc-4

我正在构建基于ASP.NET MVC4的jQuery插件,我想使用标准的Microsoft Bundler.

现在通常当我使用捆绑器时,最终用法如下:

@Scripts.Render(BundleConfig.jsBundleFile)
Run Code Online (Sandbox Code Playgroud)

在debug中使用这样的输出:

<script src="/Scripts/..."></script>
<script src="/Scripts/..."></script>
<script src="/Scripts/..."></script>
<script src="/Scripts/..."></script>
<script src="/Scripts/..."></script>
<script src="/Scripts/..."></script>
Run Code Online (Sandbox Code Playgroud)

并且官方发布中的缩小和组合文件的单个标记.

但是,因为我们正在构建一个jQuery插件,所以我想使用minifier从各种文件中插入实际的JavaScript,即在DEBUG中,当我Object1在一个文件中Object2定义并在另一个文件中定义时,我得到这个:

/* Content from file #1 */
var Object1 = function() { /* Un-minified content of Object1 */ };
/* Content from file #2 */
var Object2 = function() { /* Un-minified content of Object2 */ };
Run Code Online (Sandbox Code Playgroud)

在发布中我会得到最小化的内容.

MSDN我看到捆绑器,默认情况下不能这样做.但我想知道是否有一个扩展可以做到这个或另一个minifing库可以?虽然我更愿意留在Microsoft Bundler.

在我自己关于如何扩展System.Web.Optimizer的研究中,我找到了CodePlex项目System.Web.Optimization,据说它还不是开源的,对于没有真正开发它的人来说,扩展有点困难.

编辑:所以知道我无法真正扩展System.Web.Optimizer,我采用了妥协解决方案,这就是我最终使用的.

在控制器中:

public JavaScriptResult jQueryComponent()
{
    JavaScriptResult ret = new JavaScriptResult();
    ClientSettings Model = new ClientSettings();

#if DEBUG
    List<string> jsFiles = App_Start.BundleConfig.Main.FilesToBeBundledJS;
    StringBuilder bundleBuilder = new StringBuilder();

    foreach (string file in jsFiles)
    {
        bundleBuilder.Append(System.IO.File.ReadAllText(Server.MapPath(file)));
    }

    ViewBag.bundledJS = bundleBuilder.ToString();
#else
    StringBuilder urlBuilder = new StringBuilder("http://localhost");

    int port = Request.Url.Port;
    if (port != -1) {
        urlBuilder.Append(':');
        urlBuilder.Append(port);
    }

    urlBuilder.Append(Scripts.Url(App_Start.BundleConfig.Main.jsBundleFile));

    WebClient wc = new WebClient();
    byte[] raw = wc.DownloadData(urlBuilder.ToString());
    string bundledJS = System.Text.Encoding.UTF8.GetString(raw);

    ViewBag.bundledJS = bundledJS;
#endif

    ret.Script = RenderRazorViewToString("~/Views/Main/jQueryComponent.cshtml", Model);

    return ret;
}

private string RenderRazorViewToString(string viewName, object model)
{
    ViewData.Model = model;
    using (StringWriter sw = new StringWriter())
    {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);
        viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
        return sw.GetStringBuilder().ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

在View(jQueryComponent.cshtml)中:

@{
    Layout = null;
}

if (typeof jQuery != 'function') {
    throw "This is a jQuery plugin i.e. jQuery needs to be defined first";
}

(function ($) {

    //Adds the bundled JS into the plug-in
    @Html.Raw(ViewBag.bundledJS)

    $.fn.jsPlugIn = function() {
    /*
        Creates a new instance of [MainObject] with is defined in the bundle.
    */    
        //uses the bundled JS
        var Main = new MainObject();
        Main.doSomething();

        return this;
    };

}(jQuery));
Run Code Online (Sandbox Code Playgroud)

任何有关如何改进这一点的想法都会受到欢迎以及对捆绑者的适当扩展.

虽然有效,但这远非理想,我很清楚这一点.除非你有其他选择,否则
请不要批评这种方法.

Sam*_*ang 14

你可以做BundleHandler做什么:获取捆绑基于虚拟路径(一个你想用同一的 @Script.Render),生成响应和写入的内容.

@{
    var context = new BundleContext(this.Context, BundleTable.Bundles, string.Empty);
    var bundle = BundleTable.Bundles.GetBundleFor("~/VIRTUALPATH");
    var response = bundle.GenerateBundleResponse(context);
    var content = response.Content;

    this.WriteLiteral(content);
}
Run Code Online (Sandbox Code Playgroud)

或者简而言之:

@Html.Raw(BundleTable.Bundles.GetBundleFor("~/VIRTUALPATH").GenerateBundleResponse(new BundleContext(this.Context, BundleTable.Bundles, string.Empty)).Content)
Run Code Online (Sandbox Code Playgroud)

编辑:要获取调试unminified的内容,我们可以做什么脚本也:再次但是,而不是生成的响应获取包,我们遍历其文件和其内容写入(限定).

@{
    var context = new BundleContext(this.Context, BundleTable.Bundles, string.Empty);
    var bundle = BundleTable.Bundles.GetBundleFor("~/VIRTUALPATH");

    if (BundleTable.EnableOptimizations)
    {
        var response = bundle.GenerateBundleResponse(context);
        var content = response.Content;

        this.WriteLiteral(content);
    }
    else
    {
        var files = bundle.EnumerateFiles(context);

        foreach (var file in files)
        {
            var stream = file.VirtualFile.Open();

            using (var reader = new StreamReader(stream))
            {
                this.Output.Write("{0}{1}", reader.ReadToEnd(), bundle.ConcatenationToken);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)