自动检测 ASP.NET MVC 捆绑中的缩小失败
Automatically detect minification failures in ASP.NET MVC bundling
我不时注意到 CSS 由 ASP.NET MVC 生成的包顶部的以下错误消息:
/* Minification failed. Returning unminified contents.
(7933,26): run-time error CSS1019: Unexpected token, found ':'
(7933,26): run-time error CSS1042: Expected function, found ':'
(7933,26): run-time error CSS1062: Expected semicolon or closing curly-brace, found ':'
(7934,30): run-time error CSS1019: Unexpected token, found ':'
(7934,30): run-time error CSS1042: Expected function, found ':'
(7934,30): run-time error CSS1062: Expected semicolon or closing curly-brace, found ':'
*/
这些错误总是悄无声息地通过构建、部署和单元测试,很难被注意到。有什么解决方案可以自动捕获它们吗?很难从单元测试中得到它,因为没有内容文件夹被复制到单元测试项目中。最好这应该使构建或至少单元测试失败。
我有同样的问题,想对缩小进行单元测试,在一些错误开始尝试模拟 BundleContext
之后,我选择直接测试 webgrease Microsoft.Ajax.Utilities.Minifier
提供的缩小,轻微问题是 BundleItem
是 System.Web.Optimization 内部的,所以我不得不反思:
//arrange
BundleCollection bundles = new BundleCollection();
// my static bundler config in mvc
BundleConfig.RegisterBundles(bundles);
// act and assert
Assert.Multiple(() =>
{
foreach (var bundle in bundles)
{
// CAUTION: Reflection to private member!
var items = typeof(Bundle).GetProperty("Items", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(bundle) as IEnumerable<Object>;
foreach (Object item in items)
{
var minifier = new Minifier();
var type = item.GetType();
var path = type.GetProperty("VirtualPath")?.GetValue(item) as String;
// todo: handle "BundleDirectoryItem" too ...
if (type.Name == "BundleItem")
{
// todo: transform your virtual path to a physical path to the file at design time
var file = File.ReadAllText(path);
String min;
if (path.EndsWith("css"))
{
min = minifier.MinifyStyleSheet(file);
}
else
{
min = minifier.MinifyJavaScript(file);
}
Assert.IsNotNull(min, $"Failed to get minified output for '{path}'");
Assert.Zero(minifier.Errors.Count, $"Minification failed for '{path}', errors:\r\n{String.Join("\r\n", minifier.Errors)}");
}
}
}
});
在一个不包含测试的项目中,使用 ,我能够在加载系统时显示缩小失败的警报,虽然它没有导致编译失败,但我们设法捕获开发环境中的故障:
public static IHtmlString Render(this BundleCollection bundles, string bundleVirtualPath) {
Bundle bundle = bundles.GetBundleFor(bundleVirtualPath);
List<IHtmlString> renderTags = new List<IHtmlString>();
... omitted for simplification
List<string> errors;
if (!bundle.IsValid(out errors)) {
renderTags.Add(new HtmlString($"<script type='text/javascript'>alert('{HttpUtility.JavaScriptStringEncode(string.Join(Environment.NewLine, errors))}');</script>"));
}
return MvcHtmlString.Create(string.Join(Environment.NewLine, renderTags));
}
private static bool IsValid(this Bundle bundle, out List<string> errors) {
errors = new List<string>();
// Get items in included order
BundleContext bundleContext = new BundleContext(new HttpContextWrapper(HttpContext.Current), new BundleCollection(), Guid.NewGuid().ToString());
IEnumerable<BundleFile> bundleFiles = bundle.EnumerateFiles(bundleContext);
bool isStyleBundle = (bundle is StyleBundle);
foreach (BundleFile bundleFile in bundleFiles) {
string physicalPath = HttpContext.Current.Server.MapPath(bundleFile.IncludedVirtualPath),
fileContent = File.ReadAllText(physicalPath);
// Create minifier used by webgrease System.Web.Optimization
var minifier = new Microsoft.Ajax.Utilities.Minifier();
if (isStyleBundle) {
minifier.MinifyStyleSheet(fileContent);
} else {
minifier.MinifyJavaScript(fileContent);
}
// Verify error in minification
if (minifier.Errors.Any()) {
errors.Add($"Minification failed for {bundleFile.IncludedVirtualPath}, errors:{Environment.NewLine}{string.Join(Environment.NewLine, minifier.Errors)}");
}
}
return errors.Any();
}
希望以上代码对以后的人有所帮助。
我不时注意到 CSS 由 ASP.NET MVC 生成的包顶部的以下错误消息:
/* Minification failed. Returning unminified contents.
(7933,26): run-time error CSS1019: Unexpected token, found ':'
(7933,26): run-time error CSS1042: Expected function, found ':'
(7933,26): run-time error CSS1062: Expected semicolon or closing curly-brace, found ':'
(7934,30): run-time error CSS1019: Unexpected token, found ':'
(7934,30): run-time error CSS1042: Expected function, found ':'
(7934,30): run-time error CSS1062: Expected semicolon or closing curly-brace, found ':'
*/
这些错误总是悄无声息地通过构建、部署和单元测试,很难被注意到。有什么解决方案可以自动捕获它们吗?很难从单元测试中得到它,因为没有内容文件夹被复制到单元测试项目中。最好这应该使构建或至少单元测试失败。
我有同样的问题,想对缩小进行单元测试,在一些错误开始尝试模拟 BundleContext
之后,我选择直接测试 webgrease Microsoft.Ajax.Utilities.Minifier
提供的缩小,轻微问题是 BundleItem
是 System.Web.Optimization 内部的,所以我不得不反思:
//arrange
BundleCollection bundles = new BundleCollection();
// my static bundler config in mvc
BundleConfig.RegisterBundles(bundles);
// act and assert
Assert.Multiple(() =>
{
foreach (var bundle in bundles)
{
// CAUTION: Reflection to private member!
var items = typeof(Bundle).GetProperty("Items", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(bundle) as IEnumerable<Object>;
foreach (Object item in items)
{
var minifier = new Minifier();
var type = item.GetType();
var path = type.GetProperty("VirtualPath")?.GetValue(item) as String;
// todo: handle "BundleDirectoryItem" too ...
if (type.Name == "BundleItem")
{
// todo: transform your virtual path to a physical path to the file at design time
var file = File.ReadAllText(path);
String min;
if (path.EndsWith("css"))
{
min = minifier.MinifyStyleSheet(file);
}
else
{
min = minifier.MinifyJavaScript(file);
}
Assert.IsNotNull(min, $"Failed to get minified output for '{path}'");
Assert.Zero(minifier.Errors.Count, $"Minification failed for '{path}', errors:\r\n{String.Join("\r\n", minifier.Errors)}");
}
}
}
});
在一个不包含测试的项目中,使用
public static IHtmlString Render(this BundleCollection bundles, string bundleVirtualPath) {
Bundle bundle = bundles.GetBundleFor(bundleVirtualPath);
List<IHtmlString> renderTags = new List<IHtmlString>();
... omitted for simplification
List<string> errors;
if (!bundle.IsValid(out errors)) {
renderTags.Add(new HtmlString($"<script type='text/javascript'>alert('{HttpUtility.JavaScriptStringEncode(string.Join(Environment.NewLine, errors))}');</script>"));
}
return MvcHtmlString.Create(string.Join(Environment.NewLine, renderTags));
}
private static bool IsValid(this Bundle bundle, out List<string> errors) {
errors = new List<string>();
// Get items in included order
BundleContext bundleContext = new BundleContext(new HttpContextWrapper(HttpContext.Current), new BundleCollection(), Guid.NewGuid().ToString());
IEnumerable<BundleFile> bundleFiles = bundle.EnumerateFiles(bundleContext);
bool isStyleBundle = (bundle is StyleBundle);
foreach (BundleFile bundleFile in bundleFiles) {
string physicalPath = HttpContext.Current.Server.MapPath(bundleFile.IncludedVirtualPath),
fileContent = File.ReadAllText(physicalPath);
// Create minifier used by webgrease System.Web.Optimization
var minifier = new Microsoft.Ajax.Utilities.Minifier();
if (isStyleBundle) {
minifier.MinifyStyleSheet(fileContent);
} else {
minifier.MinifyJavaScript(fileContent);
}
// Verify error in minification
if (minifier.Errors.Any()) {
errors.Add($"Minification failed for {bundleFile.IncludedVirtualPath}, errors:{Environment.NewLine}{string.Join(Environment.NewLine, minifier.Errors)}");
}
}
return errors.Any();
}
希望以上代码对以后的人有所帮助。