2

我们希望将捆绑机制System.Web.Optimization与 Less 转换器结合使用。

问题是同一个应用程序/服务器为不同品牌的网站提供页面。因此,根据“SiteContext”,使用相同的 .less 文件,但 .less 变量应使用不同的值。因此,我们希望(重新)使用相同的更少文件,但根据请求的上下文使用不同的变量。

我尝试了几种不同的理论:

在所有 3 种情况下,我根据 SiteContext 设置不同的捆绑包。

1 通过使用拦截 variables.less 文件的自定义 VirtualPathProvider注入带有主题变量的 @import 指令。

所以我有:

  • 样式文件,例如:header.less(导入变量文件)
  • 变量文件:variables.less
  • 一个主题变量文件:variables-theme.less(通过 VirtualPathProvider 注入 variables.less)

这不起作用,因为 BundleTransformer 缓存将此视为同一个文件并且不知道 SiteContext。缓存键是基于 URL 的IAsset,我们不能影响这种行为。

2 用variables-themed.less替换 variables.less 导入,使用在 Less 转换器之前运行的自定义转换器。

再次没有运气,同样的缓存问题。

并且作为副作用,额外的转换器没有在调试中调用,因为资产没有捆绑,而是由LessAssetHandler. 这可以通过编写您自己的调用所有必需转换器的 AssetHandler 来解决。

3 创建由自定义 VirtualPathProvider解析的主题资产名称, 例如。将 header-themeX.less 添加到包中,此文件不存在,但您将此文件解析为 header.less 并使用方法 2 设置正确的变量文件导入。(将 variables.less 的导入替换为主题版本)。

再次没有运气。我认为这可以解决缓存问题,如果它不是在内部进行Bundle.Include(string virtualPath)File.Exists(path)。它不通过CustomVirtualPathProvider.


我想深入解决这个问题吗?欢迎所有想法,我可以想象随着System.Web.Optimization图书馆越来越受欢迎,这将成为越来越多的人的问题......

请记住:

  • 我们有很多 .less/css 文件
  • 我们将有5个左右的主题
  • 我们喜欢在 Visual Studio 中保持工作(这就是为什么 header.less 有一个对 variables.less 的引用)

感谢您的任何反馈。

4

1 回答 1

2

迈克尔!

您在多租户环境中使用Microsoft ASP.NET Web 优化框架Bundle Transformer,因此您需要替换 System.Web.Optimization 的一些组件并创建自己的调试 HTTP 处理程序版本(请参阅«问题:LESS文件导入被添加到 BundleResponse.Files 集合»讨论)。据我所知,Murat Cakir 在SmartStore.NET项目中解决了所有这些问题。

在 Bundle Transformer 中有两种注入 LESS 变量的方法:

  1. 查看LESS-translator的属性GlobalVariables和:ModifyVariables

    using System.Collections.Generic;
    using System.Web.Optimization;
    
    using BundleTransformer.Core.Builders;
    using BundleTransformer.Core.Orderers;
    using BundleTransformer.Core.Transformers;
    using BundleTransformer.Core.Translators;
    using BundleTransformer.Less.Translators;
    
    public class BundleConfig
    {
        public static void RegisterBundles(BundleCollection bundles)
        {
            var nullBuilder = new NullBuilder();
            var nullOrderer = new NullOrderer();
    
            var lessTranslator = new LessTranslator
            {
                GlobalVariables = "my-variable='Hurrah!'",
                ModifyVariables = "font-family-base='Comic Sans MS';body-bg=lime;font-size-h1=50px"
            };
            var cssTransformer = new CssTransformer(new List<ITranslator>{ lessTranslator });
    
            var commonStylesBundle = new Bundle("~/Bundles/BootstrapStyles");
            commonStylesBundle.Include(
               "~/Content/less/bootstrap-3.1.1/bootstrap.less");
            commonStylesBundle.Builder = nullBuilder;
            commonStylesBundle.Transforms.Add(cssTransformer);
            commonStylesBundle.Orderer = nullOrderer;
    
            bundles.Add(commonStylesBundle);
        }
    }
    
  2. 创建自定义项转换:

    using System.Text;
    using System.Web.Optimization;
    
    public sealed class InjectContentItemTransform : IItemTransform
    {
        private readonly string _beforeContent;
        private readonly string _afterContent;
    
        public InjectContentItemTransform(string beforeContent, string afterContent)
        {
            _beforeContent = beforeContent ?? string.Empty;
            _afterContent = afterContent ?? string.Empty;
        }
    
        public string Process(string includedVirtualPath, string input)
        {
            if (_beforeContent.Length == 0 && _afterContent.Length == 0)
            {
                return input;
            }
    
            var contentBuilder = new StringBuilder();
            if (_beforeContent.Length > 0)
            {
                contentBuilder.AppendLine(_beforeContent);
            }
            contentBuilder.AppendLine(input);
            if (_afterContent.Length > 0)
            {
                contentBuilder.AppendLine(_afterContent);
            }
    
            return contentBuilder.ToString();
        }
    }
    

并将此转换注册如下:

    using System.Web.Optimization;

    using BundleTransformer.Core.Orderers;
    using BundleTransformer.Core.Bundles;

    public class BundleConfig
    {
        public static void RegisterBundles(BundleCollection bundles)
        {
            var nullOrderer = new NullOrderer();

            const string beforeLessCodeToInject = @"@my-variable: 'Hurrah!';";
            const string afterLessCodeToInject = @"@font-family-base: 'Comic Sans MS';
@body-bg: lime;
@font-size-h1: 50px;";

            var commonStylesBundle = new CustomStyleBundle("~/Bundles/BootstrapStyles");
            commonStylesBundle.Include(
               "~/Content/less/bootstrap-3.1.1/bootstrap.less",
               new InjectContentItemTransform(beforeLessCodeToInject, afterLessCodeToInject));
            commonStylesBundle.Orderer = nullOrderer;

            bundles.Add(commonStylesBundle);
        }
    }

两种方式都有缺点:LESS 变量的注入在调试模式下不起作用。

于 2014-04-29T11:42:22.997 回答