ASP.NET MVC4 App在开发时无法编译Bootstrap.LESS

Ing*_*ngo 11 less asp.net-mvc-4 bundling-and-minification

我觉得现在有点卡住了.首先我用nuget来

install-package Bootstrap.less

以及

安装包无点

然后,正如Rick Andersons Blogpost关于 asp.net mvc中的捆绑和缩小所示,我创建了一个LessTransform-Class.我设置了2个几乎空的.less文件并创建了一个新的包装包装......

    var lessBundle = new Bundle("~/MyLess").IncludeDirectory("~/Content/MyLess", "*.less", true);
    lessBundle.Transforms.Add(new LessTransformer());
    lessBundle.Transforms.Add(new CssMinify());
    bundles.Add(lessBundle);
Run Code Online (Sandbox Code Playgroud)

这很好用.然后我在主bootstrap.less文件中添加了一个新的StyleBundle(基本上使用@import包含bootstrap.less发送的所有其他.less文件)...

    bundles.Add(new StyleBundle("~/Bootstrap").Include("~/Content/Bootstrap/less/bootstrap.less"));
Run Code Online (Sandbox Code Playgroud)

和一个ScriptBundle到引导程序JavaScripts ...

    bundles.Add(new ScriptBundle("~/bundles/Bootstrap").Include("~/Scripts/bootstrap/js/bootstrap-*"));
Run Code Online (Sandbox Code Playgroud)

包括所有发运的bootstrap - *.js文件和TADAA一切正常.编译CSS,包括正确加载的所有导入的JavaScript文件.

但是......所有这些只适用于开发模式

    <compilation debug="true" targetFramework="4.5"/>
Run Code Online (Sandbox Code Playgroud)

一旦我禁用调试以查看捆绑到一个文件和缩小是否正常工作我遇到问题.

捆绑过程似乎无法导入导入bootstrap.less的所有无.文件

/* Minification failed. Returning unminified contents.
(11,1): run-time error CSS1019: Unexpected token, found '/'
(11,2): run-time error CSS1019: Unexpected token, found '/'
(12,1): run-time error CSS1031: Expected selector, found '@import'
(12,1): run-time error CSS1025: Expected comma or open brace, found '@import'
(12,27): run-time error CSS1019: Unexpected token, found '/'
(12,28): run-time error CSS1019: Unexpected token, found '/'

 ... here go many many lines like these 

(60,25): run-time error CSS1019: Unexpected token, found ';'
(62,1): run-time error CSS1019: Unexpected token, found '/'
(62,2): run-time error CSS1019: Unexpected token, found '/'
(63,1): run-time error CSS1031: Expected selector, found '@import'
(63,1): run-time error CSS1025: Expected comma or open brace, found '@import'
(63,27): run-time error CSS1019: Unexpected token, found '/'
(63,28): run-time error CSS1019: Unexpected token, found '/'
: run-time error CSS1067: Unexpected end of file encountered
 */
/*!
 * Bootstrap v2.3.1 
 *
 * Copyright 2012 Twitter, Inc
 * Licensed under the Apache License v2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Designed and built with all the love in the world @twitter by @mdo and @fat.
 */

// Core variables and mixins
@import "variables.less"; // Modify this for custom colors, font-sizes, etc
@import "mixins.less";

... and the rest of the original bootstrap.less... no style definitions
Run Code Online (Sandbox Code Playgroud)

看一下缩小的bootstrap.javascript包也让我很难过.在开发中加载页面后没有问题,现在在bootstrap.javascript捆绑并在Google中缩小了JavaScript控制台状态

Uncaught TypeError: Cannot read property 'Constructor' of undefined
Run Code Online (Sandbox Code Playgroud)

我看过几个与我的问题密切相关的话题,我尝试了一些事情,但到目前为止还没有成功.

非常感谢任何能够为我的情况提供一些启示,并指出我所缺失或做错的人.最好的问候,Ingo

Ing*_*ngo 10

如果您希望将bootstrap用作较少的文件,并且另外希望不再担心开发计算机以及生产计算机上的捆绑和缩小,则可以考虑使用以下方法.

注意:如果在启用DEBUGging时只使用Less-Files,则不需要所有这些; 但是,只要您希望您的应用程序在Windows Azure等生产服务器上运行,并且仍然只想修改较少的文件而不必关心捆绑和缩小程序......那么......这种方法将会工作

所以为了解决这个问题,我觉得有点陷入困境,我不得不以不同的方式处理问题,并且不得不修改(参见后面的修改2)我认为我想要的"BundleSource".

所以不要忘记阅读本答案底部的第二次修改/警告!


修改1)

因此,工作的第一个也是最重要的部分是使无引导文件的捆绑工作.为了做到这一点,我冒昧地分叉我在网上发现的一段代码(如果你只需要一个较少的文件包)本身就解决了我的问题......除非你想使用或能够使用带有几个基本目录的多个少束...这就是我实际找到帮助我的方法的地方......

...因此我非常感谢Kristof Claes的Blog-Entry "使用ASP.NET捆绑和缩小LESS文件",我很遗憾地偶然发现了这一点.

像我一样,他试图使用Scott Hanselman在演讲中展示的LessMinify.cs来处理1个LESS文件,而不是仅仅将每个文件捆绑在一个充满LESS文件的目录中.

但他必须稍微扩展整个捆绑程序,因为他在Blog-Entry中显示.这样他建议的解决方案可以捆绑1个较少的文件,该文件使用导入来加载其他较少的文件.但是,他静态地实现了添加到源目录中的路径,在该路径中可以找到较少的文件...无论您定义的哪个包都少,都必须在同一目录中选择较少的文件...

这就是我冒昧地扩展他的解决方案的地方.我创建了一个文件LessBundling.cs,其中包含以下内容:

using dotless.Core.configuration;
using dotless.Core.Input;
using MvcApplication2.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Web;
using System.Web.Hosting;
using System.Web.Optimization;

namespace MvcApplication2.Extensions
{
    // create Less-Minifier (use Type to define source directory of less files [see below at BootstrapFileReader])
    public class LessMinify<TFileReader> : CssMinify
        where TFileReader : IFileReader
    {
        public LessMinify() {}

        public override void Process(BundleContext context, BundleResponse response)
        {
            var config = new DotlessConfiguration()
            { 
                MinifyOutput = true,
                ImportAllFilesAsLess = true,
                CacheEnabled = false,
                LessSource = typeof(TFileReader)
            };

            response.Content = dotless.Core.Less.Parse(response.Content, config);
            base.Process(context, response);
        }
    }

    // create a LessStyleBundler to allow initializing LessBundle with a single less file that uses imports
    public class LessStyleBundle<TFileReader> : Bundle
        where TFileReader : IFileReader
    {
        public LessStyleBundle(string virtualPath)
            : base(virtualPath, new LessMinify<TFileReader>()) {}

        public LessStyleBundle(string virtualPath, string cdnPath)
            : base(virtualPath, cdnPath, new LessMinify<TFileReader>()) { }
    }

    // create abstract VirtualFileReader from dotless-IFileReader as a Base for localized 
    internal abstract class VirtualFileReader : IFileReader
    {
        public byte[] GetBinaryFileContents(string fileName)
        {
            fileName = GetFullPath(fileName);
            return File.ReadAllBytes(fileName);
        }

        public string GetFileContents(string fileName)
        {
            fileName = GetFullPath(fileName);
            return File.ReadAllText(fileName);
        }

        public bool DoesFileExist(string fileName)
        {
            fileName = GetFullPath(fileName);
            return File.Exists(fileName);
        }


        public string GetFullPath(string path)
        {
            return  HostingEnvironment.MapPath(SourceDirectory + path);
        }

        public abstract string SourceDirectory {get;}
        // implement to return Path to location of less files
        // e. g. return "~/Content/bootstrap/less/";
    }

    // create BootstrapFileReader overwriting the Path where to find the Bootstrap-Less-Files
    internal sealed class BootstrapFileReader : VirtualFileReader
    {
        public override string SourceDirectory 
        {
            get { return "~/Content/bootstrap/less/"; }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

那么这实际上是做什么的呢?

  1. LessMinify扩展了CssMinify类,因此带来了缩小css文件所需的一切
    • 与"通常"捆绑的重要区别在于,您创建了一个新的Dotless-Configuration,其LessSource定义为typeof(TFileReader)...
    • 通过使用<TFileReader>,您可以定义一个类,该类将包含源目录,在该目录中,bundler/minifier将查找要考虑的较少文件
  2. LessStyleBundle扩展了Bundle,因此带来了捆绑文件所需的一切
    • 在这个类中,我再次使用TFileReader,因为这是LessMinify(er)将被实例化的地方
  3. VirtualFileReader实现了IFileReader,它是一个无点接口,定义了解析较少文件所需的所有方法,并提供了在何处查找要导入的文件的信息
    • 为了扩展Kristof的解决方案,我添加了抽象属性SourceDirectory ...要求我也要创建VirtualFileReader抽象类

现在使用该设置,您可以根据需要创建任意数量的LessFileReader.你只需要扩展抽象的VirtualFileReader,如图所示

  1. BootstrapFileReader扩展了VirtualFileReader
    • BootstrapFileReader的唯一目的是为SourceDirectory提供一个property-getter,其中bundler/minifier将找到要导入的较少文件

在我的情况下,Bootstraps Less-Files位于〜/ Content/bootstrap/less,如果您安装"twitter.bootstrap.less"-nugget,它应该是默认位置.

如果您的应用程序中有另一个目录,其中包含一个较少的文件,该文件又有多个导入,您只需创建一个扩展VirtualFileReader的新类,并为SourceDirectory定义property-getter以返回相应的路径

如果您希望使用此Bundling方法在生产环境中实际捆绑和缩小较少的文件,只需将LessStyleBundle-instantion添加到BundlerConfig.cs:

bundles.Add(new LessStyleBundle<BootstrapFileReader>("~/bundles/BootstrapCSS")
    .Include("~/Content/bootstrap/less/bootstrap.less"));
Run Code Online (Sandbox Code Playgroud)

当然你的_Layout.cshtml也应该知道随时准备好的捆绑包

@Styles.Render("~/bundles/BootstrapCSS")
Run Code Online (Sandbox Code Playgroud)

修改2)

现在是我必须添加的小修改,以使其工作

在我第一次捆绑bootstrap.less时,我使用了这个

bundles.Add(new LessStyleBundle<BootstrapFileReader>("~/Content/BootstrapCSS")
    .Include("~/Content/bootstrap/less/bootstrap.less"));
Run Code Online (Sandbox Code Playgroud)

我想我会在Javascript路由中使用CSS/Less和Bundles路由中的Content.

但这不是开箱即用的.ASP.net不允许创建以〜/ Content开头的Bundle .您将获得403授权失败.因此最简单的解决方案是使用〜/ bundles:

bundles.Add(new LessStyleBundle<BootstrapFileReader>("~/bundles/BootstrapCSS")
    .Include("~/Content/bootstrap/less/bootstrap.less"));
Run Code Online (Sandbox Code Playgroud)

由于没有太多真正的解决方案来解决这个问题,我希望如果你打算将twitter bootstrap集成到你的asp.net mvc4应用程序中,这对你们至少会有所帮助.

最好的问候,Ingo