Skip to content

Instantly share code, notes, and snippets.

@vmsp
Last active November 30, 2020 11:32
Show Gist options
  • Save vmsp/86ac52bef49fa396a22c8202b49077b6 to your computer and use it in GitHub Desktop.
Save vmsp/86ac52bef49fa396a22c8202b49077b6 to your computer and use it in GitHub Desktop.
BundleMinifier - Unbundle scripts during development and minify them for production in ASP.NET Core
<environment include="Development">
<unbundle src="~/out/site.min.css"/>
@*
Will expand to
<link rel="stylesheet" href="/css/site.css">
<link rel="stylesheet" href="/css/site2.css">
*@
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="~/out/site.min.css" asp-append-version="true"/>
@*
Will expand to
<link rel="stylesheet" href="/out/site.min.css">
*@
</environment>
...
<environment include="Development">
<unbundle src="~/out/site.min.js"/>
@*
Will expand to
<script src="/js/site.js"></script>
<script src="/js/site2.js"></script>
*@
</environment>
<environment exclude="Development">
<script src="~/out/site.min.js" asp-append-version="true"></script>
@*
Will expand to
<script src="/out/site.min.js"></script>
*@
</environment>
[
{
"outputFileName": "~/out/site.min.css",
"inputFiles": [
"~/css/site.css",
"~/css/site2.css"
]
},
{
"outputFileName": "~/out/site.min.js",
"inputFiles": [
"~/js/site.js",
"~/js/site2.js"
]
}
]
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Newtonsoft.Json;
namespace MyApp.TagHelpers
{
public class UnbundleTagHelper : TagHelper
{
private readonly IUrlHelperFactory _urlHelperFactory;
private readonly IWebHostEnvironment _webHostEnvironment;
public UnbundleTagHelper(IUrlHelperFactory urlHelperFactory, IWebHostEnvironment webHostEnvironment)
{
_urlHelperFactory = urlHelperFactory;
_webHostEnvironment = webHostEnvironment;
}
public string Src { get; set; }
[HtmlAttributeNotBound] [ViewContext] public ViewContext ViewContext { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
var urlHelper = _urlHelperFactory.GetUrlHelper(ViewContext);
var bundleConfigPath = Path.Combine(_webHostEnvironment.ContentRootPath, "bundleconfig.json");
var inputFiles = FindInputFiles(bundleConfigPath);
output.TagName = null;
if (Src.EndsWith("css"))
foreach (var inputFile in inputFiles)
OutputStylesheet(urlHelper, inputFile, output);
else
foreach (var inputFile in inputFiles)
OutputScript(urlHelper, inputFile, output);
}
private void OutputStylesheet(IUrlHelper urlHelper, string inputFile, TagHelperOutput output)
{
var link = new TagBuilder("link");
link.Attributes.Add("rel", "stylesheet");
link.Attributes.Add("href", urlHelper.Content(inputFile));
link.TagRenderMode = TagRenderMode.SelfClosing;
output.Content.AppendHtml(link);
}
private void OutputScript(IUrlHelper urlHelper, string inputFile, TagHelperOutput output)
{
var script = new TagBuilder("script");
script.Attributes.Add("src", urlHelper.Content(inputFile));
output.Content.AppendHtml(script);
}
private IEnumerable<string> FindInputFiles(string bundleConfigPath)
{
var bundles = JsonConvert.DeserializeObject<IEnumerable<Bundle>>(File.ReadAllText(bundleConfigPath));
foreach (var bundle in bundles)
if (bundle.OutputFileName == Src)
return bundle.InputFiles;
return Enumerable.Empty<string>();
}
private class Bundle
{
[JsonProperty("outputFileName")] public string OutputFileName { get; set; }
[JsonProperty("inputFiles")] public IList<string> InputFiles { get; set; }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment