ASP.NET MVC4 Bundle a single file

2020-06-16 01:03发布

问题:

Is there a way to bundle a single file using the new bundling features in MVC4? I know bundling a single file doesn't make much sense but I'd like to use server-side minification and let MVC append a hash on to the end of the URL for caching purposes.

I've tried the @Scripts.Url("~/Scripts/myscript.js") but it doesn't appear to work.

回答1:

Well, define a bundle containing only this file in your bundle config:

bundles.Add(
    new ScriptBundle("~/bundles/myscript").Include("~/Scripts/myscript.js")
);

and then use it in your view by referencing it by name:

@Scripts.Render("~/bundles/myscript")


回答2:

I needed something like this, and here's what I came up with

On a view I can add a script or style with an HTML Helper. These will each accept n number of parameters.

@Html.Style("~/Styles/someFile.css")
@Html.Script("~/Scripts/foo.js", "~/Scripts/bar.js")

So I created an extention to handle this for me. Here's what the class looks like.

using System.Linq;
using System.Web.Optimization;

namespace System.Web.Mvc
{
    public static class HtmlHelperExtensions
    {

        public static IHtmlString Script(this HtmlHelper helper, params string[] urls)
    {
        var bundleDirectory = "~/Scripts/bundles/" + MakeBundleName(".js", urls);
        var thisBundle = new ScriptBundle(bundleDirectory).Include(urls);
        BundleTable.Bundles.Add(thisBundle);

        return Scripts.Render(bundleDirectory);
    }

    public static IHtmlString Style(this HtmlHelper helper, params string[] urls)
    {
        var bundleDirectory = "~/Styles/bundles/" + MakeBundleName(".css", urls);
        var thisBundle = new StyleBundle(bundleDirectory).Include(urls);
        BundleTable.Bundles.Add(thisBundle);

        return Styles.Render(bundleDirectory);
    }

    private static string MakeBundleName(string type, params string[] urls)
    {
        var bundleSections = new List<string>();

        foreach (var item in urls)
        {
            bundleSections.Add(item.Replace("~/", "").Replace("/", ".").Replace(type, ""));
        }

        return string.Join("+", bundleSections.ToArray());
    }
    }
}

Caveats

This does hard code where the bundle "virtual directory" exists. So if you have any relative paths to images or anything else in your files, they will break. For our use case, this works fine for us for now.

The bundle names are auto-generated. Again, this works for us, but it could be better. I could see a simple improvement to this where you must provide a bundle path & name that would have a syntax like this: @Html.Script("~/bundles/myBundleName","~/Scripts/foo.js", "~/Scripts/bar.js")


I'd be happy to hear about any improvements anyone might have for this.



回答3:

I dont know, if I get you right, but you can add bundles any time you want to, just add it to the bundlecollection:

BundleTable.Bundles.Add(new ScriptBundle("~/Scripts/myBundleName").Include(
            "~/Scripts/myscript.js"
            ));

I am not sure how you planing to include the bundle on client side, but after a bundle is registered you can get the url of the minified script file with this code:

string url = BundleTable.Bundles.ResolveBundleUrl("~/Scripts/myBundleName");

In my case I just get this url through an ajax request and create a script tag on client side. This way the script file will be minified and the url comes with an hash code, so the browser should cache it and when the bundle is changed should load the newer version.

I hope this is, what you intended to do.