本文介绍了BundleTransformer.Less根据上下文/请求注入变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们希望将System.Web.Optimization的捆绑机制与Less变压器结合使用.

We would like the use the bundling mechanism of System.Web.Optimization in combination with the Less transformer.

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

The problem is that the same application/server serves pages for different branded websites. So depending on the 'SiteContext' the same .less files are used but different values should be used by the .less variables. So we want the (re)use the same less files but with different variables depending on the context of the request.

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

I tried a couple of different theories:

在所有3种情况下,我都会根据SiteContext设置不同的捆绑软件.

In all 3 cases I setup different bundles depending on the SiteContext.

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

1 inject an @import directive with the themed variables by using a custom VirtualPathProvider that intercepts the variables.less file.

所以我有

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

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

This is not working because the BundleTransformer cache sees this as the same file and doesn't know about the SiteContext. The cache key is based on the Url of the IAsset and we cannot influence this behavior.

2用以主题为主题的less.替换以variables-them.less为变量的,该变量在less变换器之前运行的自定义变换器.

2 Replace the variables.less import by variables-themed.less with an custom transformer that runs before the Less transformer.

没有运气,同样的缓存问题.

Again no luck, same caching issues.

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

And as a side effect, the extra transformer was not called in debug because the assets are not bundled but called individually by the LessAssetHandler. This could be solved by writing your own AssetHandler that calls all required transformers.

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

3 create themed Asset names that are resolved by a custom VirtualPathProviderEg. Add header-themeX.less to the bundle, this file doesn't exist but you resolve this file to header.less and use method 2 to set the correct variables file import. (replace the import of the variables.less to the themed version).

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

Once again no luck. I think this could solve the caching issue if it wasn't for the Bundle.Include(string virtualPath) that does a File.Exists(path) internally. It doesn't pass via the CustomVirtualPathProvider.

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

Am I looking to deep to solve this?All ideas are welcome, I can imagine that this will become a problem to more and more people as the System.Web.Optimization library gets more popular...

请记住:

  • 我们有很多.less/css文件
  • 我们将有5个左右的主题
  • 我们希望在Visual Studio中保持工作正常(这就是为什么header.less引用了variables.less的原因)

谢谢您的反馈.

推荐答案

迈克尔!

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

You use the Microsoft ASP.NET Web Optimization Framework and the Bundle Transformer in multi-tenant environment, so you need to replace some components of the System.Web.Optimization and create own versions of the debugging HTTP-handlers (see «Problem: LESS file imports are added to BundleResponse.Files collection» discussion). As far as I know, Murat Cakir solve all these problems in the SmartStore.NET project.

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

In the Bundle Transformer there are 2 ways to inject of LESS-variables:

  1. 查找LESS-translator的属性GlobalVariablesModifyVariables:

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);
    }
}

  • 创建自定义项目转换:

  • Create a custom item transformation:

    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();
        }
    }
    

  • 并按如下所示注册此转换:

    And register this transformation as follows:

        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变量的注入在调试模式下不起作用.

    Both ways have disadvantage: the injection of LESS-variables does not work in debug mode.

    这篇关于BundleTransformer.Less根据上下文/请求注入变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    09-23 17:06