How to use ASP.Net MVC 4 to Bundle LESS files in Release mode?

后端 未结 5 1322
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-04 13:46

I\'m trying to have LESS files in my web project, and have the MVC 4 bundling functionality call into the dotLess library to turn the LESS into CSS, then minify the result a

5条回答
  •  伪装坚强ぢ
    2020-12-04 14:01

    The accepted answer does not work with recent changes to ASP.NET, so is no longer correct.

    I've fixed the source in the accepted answer:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Web.Hosting;
    using System.Web.Optimization;
    using dotless.Core;
    using dotless.Core.Abstractions;
    using dotless.Core.Importers;
    using dotless.Core.Input;
    using dotless.Core.Loggers;
    using dotless.Core.Parser;
    
    namespace Web.App_Start.Bundles
    {
        public class LessTransform : IBundleTransform
        {
            public void Process(BundleContext context, BundleResponse bundle)
            {
                if (context == null)
                {
                    throw new ArgumentNullException("context");
                }
    
                if (bundle == null)
                {
                    throw new ArgumentNullException("bundle");
                }
    
                context.HttpContext.Response.Cache.SetLastModifiedFromFileDependencies();
    
                var lessParser = new Parser();
                ILessEngine lessEngine = CreateLessEngine(lessParser);
    
                var content = new StringBuilder(bundle.Content.Length);
    
                var bundleFiles = new List();
    
                foreach (var bundleFile in bundle.Files)
                {
                    bundleFiles.Add(bundleFile);
    
                    var name = context.HttpContext.Server.MapPath(bundleFile.VirtualFile.VirtualPath);
                    SetCurrentFilePath(lessParser, name);
                    using (var stream = bundleFile.VirtualFile.Open())
                    using (var reader = new StreamReader(stream))
                    {
                        string source = reader.ReadToEnd();
                        content.Append(lessEngine.TransformToCss(source, name));
                        content.AppendLine();
                    }
    
                    bundleFiles.AddRange(GetFileDependencies(lessParser));
                }
    
                if (BundleTable.EnableOptimizations)
                {
                    // include imports in bundle files to register cache dependencies
                    bundle.Files = bundleFiles.Distinct();
                }
    
                bundle.ContentType = "text/css";
                bundle.Content = content.ToString();
            }
    
            /// 
            /// Creates an instance of LESS engine.
            /// 
            /// The LESS parser.
            private ILessEngine CreateLessEngine(Parser lessParser)
            {
                var logger = new AspNetTraceLogger(LogLevel.Debug, new Http());
                return new LessEngine(lessParser, logger, true, false);
            }
    
            /// 
            /// Gets the file dependencies (@imports) of the LESS file being parsed.
            /// 
            /// The LESS parser.
            /// An array of file references to the dependent file references.
            private IEnumerable GetFileDependencies(Parser lessParser)
            {
                IPathResolver pathResolver = GetPathResolver(lessParser);
    
                foreach (var importPath in lessParser.Importer.Imports)
                {
                    yield return
                        new BundleFile(pathResolver.GetFullPath(importPath),
                            HostingEnvironment.VirtualPathProvider.GetFile(importPath));
                }
    
                lessParser.Importer.Imports.Clear();
            }
    
            /// 
            /// Returns an  instance used by the specified LESS lessParser.
            /// 
            /// The LESS parser.
            private IPathResolver GetPathResolver(Parser lessParser)
            {
                var importer = lessParser.Importer as Importer;
                var fileReader = importer.FileReader as FileReader;
    
                return fileReader.PathResolver;
            }
    
            /// 
            /// Informs the LESS parser about the path to the currently processed file. 
            /// This is done by using a custom  implementation.
            /// 
            /// The LESS parser.
            /// The path to the currently processed file.
            private void SetCurrentFilePath(Parser lessParser, string currentFilePath)
            {
                var importer = lessParser.Importer as Importer;
    
                if (importer == null)
                    throw new InvalidOperationException("Unexpected dotless importer type.");
    
                var fileReader = importer.FileReader as FileReader;
    
                if (fileReader == null || !(fileReader.PathResolver is ImportedFilePathResolver))
                {
                    fileReader = new FileReader(new ImportedFilePathResolver(currentFilePath));
                    importer.FileReader = fileReader;
                }
            }
        }
    }
    

    Please note one known issue with this code as is is that LESS @imports must use their full paths, i.e. you must use @import "~/Areas/Admin/Css/global.less"; instead of @import "global.less";.

提交回复
热议问题