我们希望将System.Web.Optimization
的捆绑机制与Less transformer结合使用。
问题是相同的应用程序/服务器为不同品牌的网站提供页面。因此,根据'SiteContext',使用相同的.less文件,但.less变量应使用不同的值。因此,我们希望(重新)使用相同的较少文件,但具有不同的变量,具体取决于请求的上下文。
我尝试了几种不同的理论:
在所有3种情况下,我根据SiteContext设置了不同的包。
1使用主题变量注入@import指令,方法是使用拦截variables.less文件的自定义VirtualPathProvider 。
所以我有:
这不起作用,因为BundleTransformer缓存将此视为同一文件,并且不知道SiteContext。缓存密钥基于IAsset
的Url,我们无法影响此行为。
2使用变量-themed.less替换variables.less import ,并在Less变换器之前运行自定义变换器。
再次没有运气,同样的缓存问题。
作为副作用,额外的变换器未在调试中调用,因为资产未捆绑但由LessAssetHandler
单独调用。这可以通过编写调用所有必需变换器的自己的AssetHandler来解决。
3创建主题资产名称 例如。将header-themeX.less添加到包中,此文件不存在,但您将此文件解析为header.less并使用方法2设置正确的变量文件导入。 (将变量的导入替换为主题版本。)
再一次没有运气。我认为这可以解决缓存问题,如果不是内部Bundle.Include(string virtualPath)
的{{1}}。它不会通过File.Exists(path)
传递。
我是否希望能够解决这个问题?
欢迎所有的想法,我可以想象随着CustomVirtualPathProvider
图书馆越来越受欢迎,这将成为越来越多人的问题......
请记住:
感谢您的反馈。
答案 0 :(得分:2)
迈克尔!
您在多租户环境中使用Microsoft ASP.NET Web Optimization Framework和Bundle Transformer,因此您需要替换System.Web.Optimization的某些组件并创建自己的调试HTTP处理程序版本(请参阅«Problem: LESS file imports are added to BundleResponse.Files collection»讨论)。据我所知,Murat Cakir在SmartStore.NET项目中解决了所有这些问题。
在Bundle Transformer中有两种注入LESS变量的方法:
查看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);
}
}
创建自定义项目转换:
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变量在调试模式下不起作用。