ASP.NET MVC5 Bundling and Minification

发布时间 2023-11-24 15:20:05作者: talentzemin

代码

var myScriptBundle = new ScriptBundle("~/bundles/script").Include("~/Scripts/myscript.js");
bundles.Add(myScriptBundle);

var myStyleBundle = new StyleBundle("~/Content/css").Include("~/Content/Login/mycss.css")
bundles.Add(mfaStyleBundle);

不起作用?

有两种办法使其生效
第一就是修改web.config

 <system.web>
        <compilation  debug="false" />
 </system.web>

第二就是在代码中直接指定,不管web.config中是不是debug都使其生效

 BundleTable.EnableOptimizations = true;

缓存问题

如果修改了css和js文件,而用户浏览器存在缓存,不能无感更新,用户要手动强制刷新或者清除缓存
解决该问题,我们希望每次文件发布后,都有不同的“版本号”,如果未更改文件,那么也不用更新“版本号”
你也看出来了,这个“版本号”与文件内容有关系,所以取文件哈希值最合适

public class BundleTransformer : IBundleTransform
{
    public void Process(BundleContext context, BundleResponse response)
    {
        foreach (var file in response.Files)
        {
            using (var fileStream = File.OpenRead(HostingEnvironment.MapPath(file.IncludedVirtualPath)))
            {
                var hashBytes = new MD5CryptoServiceProvider().ComputeHash(fileStream);
                var version = string.Join(null, hashBytes.Select(value => value.ToString("x2")));
                file.IncludedVirtualPath = string.Concat(file.IncludedVirtualPath, $"?v={version}");
            }
        }
    }
}

使用

var myScriptBundle = new ScriptBundle("~/bundles/script").Include("~/Scripts/myscript.js");
myScriptBundle .Transforms.Add(new BundleTransformer());//new
bundles.Add(myScriptBundle);

var myStyleBundle = new StyleBundle("~/Content/css").Include("~/Content/Login/mycss.css")
myStyleBundle.Transforms.Add(new BundleTransformer());//new
bundles.Add(mfaStyleBundle);

CSS 中图片路径失效问题

一般我们写css的时候,比如背景图都会写下相对路径

div{background-img: url(../images/logo.png);}

当我们的虚拟路径(假设设置为/Content/css)和css文件(/Content/css/order/index.css)的路径不一致的时候,css文件中的图片这个时候就会出现找不到的问题
所以,此时css中的image的路径应该相对虚拟路径,而不是相对css文件了
就没有好办法吗?有

var myStyleBundle = new StyleBundle("~/Content/css")
.Include("~/Content/XXX/index.css", new CssRewriteUrlTransform())
.Include("~/Content/YYY/index.css", new CssRewriteUrlTransform());//new

bundles.Add(myStyleBundle);

我们看下CssRewriteUrlTransform的实现

public class CssRewriteUrlTransform : IItemTransform
{
    public CssRewriteUrlTransform()
    {
    }

    internal static string RebaseUrlToAbsolute(string baseUrl, string url)
    {
        if (string.IsNullOrWhiteSpace(url) || string.IsNullOrWhiteSpace(baseUrl) || url.StartsWith("/", StringComparison.OrdinalIgnoreCase))
        {
            return url;
        }

        if (!baseUrl.EndsWith("/", StringComparison.OrdinalIgnoreCase))
        {
            baseUrl += "/";
        }

        return VirtualPathUtility.ToAbsolute(baseUrl + url);
    }

    internal static string ConvertUrlsToAbsolute(string baseUrl, string content)
    {
        if (string.IsNullOrWhiteSpace(content))
        {
            return content;
        }

        Regex regex = new Regex("url\\(['\"]?(?<url>[^)]+?)['\"]?\\)");
        return regex.Replace(content, (Match match) => "url(" + RebaseUrlToAbsolute(baseUrl, match.Groups["url"].Value) + ")");
    }

    public string Process(string includedVirtualPath, string input)
    {
        if (includedVirtualPath == null)
        {
            throw new ArgumentNullException("includedVirtualPath");
        }

        string directory = VirtualPathUtility.GetDirectory(includedVirtualPath.Substring(1));
        return ConvertUrlsToAbsolute(directory, input);
    }
}

代码一看就懂,通过正则表达式给你重写下css中的url路径

但是,偏偏又有一种场景,你的网站如果部署IIS 的 application,那么你会发现上面的写法又又失效了
比如你的网站访问url是:http://localhost/sample/
你期望css中image url是: http://localhost/sample/content/images/logo.png
但是上面的方法得到的却是:http://localhost/content/images/logo.png
缺少了application的名称!

再改改呗

public class CssRewriteUrlTransformWrapper : IItemTransform
{
    public string Process(string includedVirtualPath, string input)
    {
        return new CssRewriteUrlTransform().Process("~" + VirtualPathUtility.ToAbsolute(includedVirtualPath), input);
    }
}

使用

var myStyleBundle = new StyleBundle("~/Content/css")
.Include("~/Content/XXX/index.css", new CssRewriteUrlTransformWrapper())
.Include("~/Content/YYY/index.css", new CssRewriteUrlTransformWrapper());//new

bundles.Add(myStyleBundle);

Ref

https://learn.microsoft.com/en-us/aspnet/mvc/overview/performance/bundling-and-minification
https://stackoverflow.com/questions/32422223/mvc-bundling-and-relative-css-image-when-website-is-deployed-to-an-application
https://www.cnblogs.com/susilent/archive/2013/03/01/2939196.html