11

私は今少し立ち往生しているように感じます。最初にnugetを使用して

install-package Bootstrap.less

と同様

インストール-パッケージドットレス

次に、 asp.netmvcでのバンドルとミニファイに関するRickAndersons Blogpostに示されているように、LessTransform-Classを作成しました。ほぼ空の.lessファイルを2つ設定し、それらをパッケージ化した新しいバンドルを作成しました...

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

それはうまくいきました。次に、新しいStyleBundleをメインのbootstrap.lessファイルに追加しました(基本的に@importを使用して、bootstrap.lessが出荷する他のすべての.lessファイルを含めます)...

    bundles.Add(new StyleBundle("~/Bootstrap").Include("~/Content/Bootstrap/less/bootstrap.less"));

ブートストラップJavaScriptへのScriptBundle...

    bundles.Add(new ScriptBundle("~/bundles/Bootstrap").Include("~/Scripts/bootstrap/js/bootstrap-*"));

出荷されたすべてのbootstrap-*。jsファイルとTADAAを含めると、すべて正常に機能しました。インポートされたすべてのJavaScriptファイルを含むCSSがコンパイルされ、正しくロードされました。

しかし...すべては開発モードでのみ機能しました

    <compilation debug="true" targetFramework="4.5"/>

デバッグを無効にして、1つのファイルへのバンドルとミニファイが適切に機能するかどうかを確認するとすぐに、問題が発生します。

バンドルプロセスでは、bootstrap.lessにインポートされたすべての.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

縮小されたbootstrap.javascriptバンドルを見ると、私も困惑します。開発では、ページを読み込んだ後も問題はありませんでした。bootstrap.javascriptがバンドルされてGoogleで縮小された後、JavaScriptコンソールは次のように述べています。

Uncaught TypeError: Cannot read property 'Constructor' of undefined

私は自分の問題に密接に関連していると思われるいくつかのトピックを見て、いくつかのことを試しましたが、これまでのところ成功していません。

私の状況に光を当てることができ、私が欠けていることや間違っていることを指摘してくれる人に、事前に感謝します。よろしく、インゴ

4

4 に答える 4

10

ブートストラップをless-filesとして使用し、さらに開発マシンと本番マシンでのバンドルとミニファイについて心配するのをやめたい場合は、次のアプローチの使用を検討してください。

注:デバッグが有効になっているときにLess-Filesだけを試してみる場合は、これらすべては必要ありません。ただし、アプリケーションをWindows Azureなどの運用サーバーで稼働させ、バンドルやミニファイの手順を気にすることなく、少ないファイルを変更したい場合は、すぐにこのアプローチを使用します。仕事

そのため、少し行き詰まったと感じた問題を解決するために、別の方法で問題にアプローチし、必要だと思った「BundleSource」を変更する必要がありました(投稿のさらに下の変更2を参照)。

したがって、この回答の下部にある2番目の変更/警告を読むことを忘れないでください!


変更1)

したがって、仕事の最初の大きな部分は、ブートストラップのないファイルのバンドルを機能させることです。それを行うために、私は自由にWebで見つけたコードの一部をフォークしました。これは、(ファイルバンドルが1つだけ必要な場合は)それ自体で問題を解決します...使用したい場合や使用できる場合を除きます。いくつかのベースディレクトリを持つ複数のless-bundles...そこで私は実際に私を大いに助けたアプローチを見つけました...

...そのため、偶然に偶然見つけたブログエントリ「ASP.NETのバンドルとLESSファイルでの縮小の使用」についてKristofClaesに感謝します。

私のように、彼はスピーチでスコット・ハンゼルマンが示したLessMinify.csを使用して、LESSファイルでいっぱいの1つのディレクトリにすべてのファイルをバンドルするのではなく、1つのLESSファイルを処理しようとしました。

しかし、彼はブログエントリに示されているように、バンドル手順全体をわずかに延長する必要がありました。このようにして、彼が提案するソリューションは、インポートを使用して他の少ないファイルをロードする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/"; }
        }
    }

}

では、これは実際に何をするのでしょうか?

  1. LessMinifyはCssMinifyクラスを拡張するため、cssファイルの縮小に必要なすべてのものを提供します
    • 「通常の」バンドルとの重要な違いは、typeof(TFileReader)として定義されたLessSourceを使用して新しいドットレス構成を作成することです...
    • <TFileReader>を使用すると、バンドラー/ミニファイアが考慮されるファイルの数を減らすソースディレクトリを含むクラスを定義できます。
  2. LessStyleBundleはBundleを拡張するため、ファイルをバンドルするために必要なすべてのものを提供します
    • このクラスでは、LessMinify(er)がインスタンス化される場所であるため、ここでもTFileReaderを使用します。
  3. VirtualFileReaderは、IFileReaderを実装します。これは、より少ないファイルを解析し、インポートするファイルの場所に関する情報を提供するために必要なすべてのメソッドを定義するドットレスインターフェイスです。
    • Kristofのソリューションを問題に拡張するために、抽象プロパティSourceDirectoryを追加しました...VirtualFileReader抽象クラスも作成する必要があります

この設定で、必要な数のLessFileReaderを作成できます。に見られるように、抽象VirtualFileReaderを拡張する必要があります

  1. BootstrapFileReaderはVirtualFileReaderを拡張します
    • BootstrapFileReaderの唯一の目的は、ソースディレクトリのプロパティゲッターを用意することです。このプロパティゲッターでは、バンドラー/ミニファイアがインポートされるファイルの数を減らします。

私の場合、Bootstraps Less-「twitter.bootstrap.less」をインストールした場合のデフォルトの場所である〜/ Content / bootstrap/lessにあるファイル-ナゲット。

アプリケーションに別のディレクトリがあり、そこに複数のインポートがある少ないファイルが含まれている場合は、VirtualFileReaderを拡張する新しいクラスを作成し、SourceDirectoryが対応するパスを返すようにプロパティゲッターを定義するだけです。

次に、このバンドル方法を使用して、実稼働環境で実際に少ないファイルをバンドルおよび縮小する場合は、LessStyleBundleインスタンスをBundlerConfig.csに追加するだけです。

bundles.Add(new LessStyleBundle<BootstrapFileReader>("~/bundles/BootstrapCSS")
    .Include("~/Content/bootstrap/less/bootstrap.less"));

もちろん、_Layout.cshtmlは、すぐに準備できるバンドルにも注意する必要があります。

@Styles.Render("~/bundles/BootstrapCSS")

変更2)

これを機能させるために追加しなければならなかったマイナーな変更

bootstrap.lessをバンドルする最初の試みで、これを使用しました

bundles.Add(new LessStyleBundle<BootstrapFileReader>("~/Content/BootstrapCSS")
    .Include("~/Content/bootstrap/less/bootstrap.less"));

CSS / LessのルートではContentを使用し、JavascriptのルートではBundlesを使用すると思いました。

しかし、それはそのままでは機能しません。ASP.netでは、〜/Contentで始まるバンドルの作成は許可されていません。403認証に失敗します。したがって、これに対する最も簡単な解決策は、代わりに〜/bundlesを使用することです。

bundles.Add(new LessStyleBundle<BootstrapFileReader>("~/bundles/BootstrapCSS")
    .Include("~/Content/bootstrap/less/bootstrap.less"));

この問題に対する実際の解決策は多くないので、twitterブートストラップをasp.net mvc4アプリケーションに統合することを計画している場合、これが少なくとも一部のユーザーに役立つことを願っています。

よろしく、インゴ

于 2013-03-27T00:02:23.477 に答える
3

Ingoの回避策を変更して、各ディレクトリのカスタムクラスを削除しました。また、適切な例外出力を追加しました(それ以外の場合は、すべての例外がサイレントであり、エラーが発生した場合に空のファイルが少なくなるためです)。

public class LessTransform : IItemTransform
{
    [ThreadStatic]
    internal static string CurrentParsedFileDirectory;


    public string Process (string includedVirtualPath, string input)
    {
        CurrentParsedFileDirectory = Path.GetDirectoryName (includedVirtualPath);

        var config = new DotlessConfiguration
        {
            MinifyOutput = false,
            CacheEnabled = false,
            MapPathsToWeb = true,
            ImportAllFilesAsLess = true,
            LessSource = typeof (VirtualFileReader),
            Logger = typeof (ThrowExceptionLogger)
        };

        return Less.Parse (input, config);
    }
}


internal class VirtualFileReader : IFileReader
{
    public bool UseCacheDependencies
    {
        get { return false; }
    }


    public byte[] GetBinaryFileContents (string fileName)
    {
        return File.ReadAllBytes (GetFullPath (fileName));
    }


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


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


    public string GetFullPath (string path)
    {
        if (string.IsNullOrEmpty (path))
            return string.Empty;

        return HostingEnvironment.MapPath (path[0] != '~' && path[0] != '/'
                                               ? Path.Combine (LessTransform.CurrentParsedFileDirectory, path)
                                               : path);
    }
}


public class ThrowExceptionLogger : Logger
{
    public ThrowExceptionLogger (LogLevel level) : base (level)
    {
    }


    protected override void Log (string message)
    {
        if (string.IsNullOrEmpty (message))
            return;

        if (message.Length > 100)
            message = message.Substring (0, 100) + "...";

        throw new LessTransformException (message);
    }
}


[Serializable]
public sealed class LessTransformException : Exception
{
    public LessTransformException (string message) : base (message)
    {
    }
}

使用法:

bundles.Add (new StyleBundle ("~/styles-bundle/common")
    .Include ("~/content/bootstrap/bootstrap.less", new LessTransform ()));
于 2013-12-25T12:26:28.947 に答える
2

今日も同じ問題が発生していました。回避策を見つけましたが、より良い解決策も必要です。私はまた、ドットレスとあなたが持っているようなカスタム変換を使おうとしていました。

回避策:

ビルド前のイベント:

"$(SolutionDir)packages\dotless.1.3.1.0\tool\dotless.compiler.exe" "$(ProjectDir)Content\less\bootstrap.less"

これにより、の代わりにbootstrap.css通常どおりに含めることができるファイルが作成されます。CSSLESS

このソリューションは理想的ではありません。ドットレスを更新するたびにビルドイベントを更新する必要があり、バンドルに処理させることで、よりクリーンになります。

于 2013-03-13T08:04:53.397 に答える
0

代わりに、 WebEssentials2012をインストールすることを強くお勧めします。

.lessからcss-fileと縮小されたcss-fileが生成され、代わりにcssを参照できます。.lessに変更を加えるたびに、cssが自動的に更新されるため、ビルド前の手順などを覚えておく必要はありません...

WebEssentialsをインストールすると、CoffeeScript、TypeScript、LESSのプレビューなどの他の優れた機能も利用できます。JSHint、自動ミニファイ、そしてもっとたくさんの「グッズ」!

于 2013-06-25T08:46:15.200 に答える