2012-08-15 16 views
44

Próbuję użyć łączenia, aby połączyć & zminimalizować niektóre pliki CSS. W moim Global.aspx.cs Application_Start mam następujące:Łączenie MVC4 CSS nie powiodło się Nieoczekiwany token, znaleziony "@import"

var jsBundle = new Bundle("~/JSBundle", new JsMinify()); 
    jsBundle.AddDirectory("~/Scripts/", "*.js", false); 
    jsBundle.AddFile("~/Scripts/KendoUI/jquery.min.js"); 
    jsBundle.AddFile("~/Scripts/KendoUI/kendo.web.min.js"); 
    BundleTable.Bundles.Add(jsBundle); 

    var cssBundle = new Bundle("~/CSSBundle", new CssMinify()); 
    cssBundle.AddDirectory("~/Content/", "*.css", false); 
    cssBundle.AddDirectory("~/Content/themes/base/", "*.css", false); 
    cssBundle.AddFile("~/Styles/KendoUI/kendo.common.min.css"); 
    cssBundle.AddFile("~/Styles/KendoUI/kendo.default.min.css"); 
    BundleTable.Bundles.Add(cssBundle); 

I w moim .cshtml pliku mam następujące:

<link href="/CSSBundle" rel="stylesheet" type="text/css" /> 
<script src="/JSBundle" type="text/javascript"></script> 

Jednak, kiedy zobaczyć źródło mojego pliku wiązki CSS , ma następujące elementy:

/* Minification failed. Returning unminified contents. 
(40,1): run-time error CSS1019: Unexpected token, found '@import' 
(40,9): run-time error CSS1019: Unexpected token, found '"jquery.ui.base.css"' 

.... wiele innych

Wszelkie pomysły na nowo rozwiązać to?

zrobiłem sprowadzić do następującej linii:

cssBundle.AddDirectory("~/Content/themes/base/", "*.css", false); 

Jeśli mam tylko tę linię kodu dostaję te same błędy.

Odpowiedz

44

Istnieje kilka kwestii tutaj:

  1. Kwestia css to spowodowane tym jquery.ui.all.css, jako domyślny minifier nie obsługuje następujące importu, a to nie to, co jest chcesz zrobić tak czy inaczej, ponieważ podwoiłoby to wszystkie pliki jquery ui css. Więc co chcesz zrobić, zamiast nie używać * .css, a zamiast jawnie listy plików co jquery ui chcesz dołączyć:

    bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
         "~/Content/themes/base/jquery.ui.core.css", 
         "~/Content/themes/base/jquery.ui.resizable.css", 
         "~/Content/themes/base/jquery.ui.selectable.css", 
         "~/Content/themes/base/jquery.ui.accordion.css", 
         "~/Content/themes/base/jquery.ui.autocomplete.css", 
         "~/Content/themes/base/jquery.ui.button.css", 
         "~/Content/themes/base/jquery.ui.dialog.css", 
         "~/Content/themes/base/jquery.ui.slider.css", 
         "~/Content/themes/base/jquery.ui.tabs.css", 
         "~/Content/themes/base/jquery.ui.datepicker.css", 
         "~/Content/themes/base/jquery.ui.progressbar.css", 
         "~/Content/themes/base/jquery.ui.theme.css")); 
    
  2. drugie chcesz używać metody Script/Styles.Render zamiast jawne odwoływanie się do adresu URL pakietów, tak jak to robisz, ponieważ pomocnicy nie będą automatycznie pakować/minimalizować i renderować indywidualnych odwołań do każdego skryptu/zasobu stylów w trybie debugowania, a także dodawać odcisk palca do zawartości pakietu w adresie URL, aby buforowanie działaj dobrze.

    @Scripts.Render("~/JSBundle") and @Styles.Render("~/CSSBundle") 
    
  3. Można również użyć StyleBundle/ScriptBundle który jest cukier tylko syntaxtic za nie konieczności przechodzenia w nowym CSS/JsMinify.

Można również sprawdzić ten poradnik, aby uzyskać więcej informacji: Bundling Tutorial

+2

Brakowało ci "~/Content/themes/base/jquery.ui.menu.css" i "~/Content/themes/base/jquery.ui.spinner.css". –

+0

NIESAMOWITA odpowiedź! : D Zrzuć dużo światła ... –

+2

Cóż, nie ma w pakiecie, gdy napotyka takie rzeczy jak @ -webkit-klatki kluczowe, więc nie jest to tylko błąd na @import. – Triynko

10

Albo co można zrobić, to napisać własny BundleTransform dla CssMinify jeśli oczywiście trzeba taką elastyczność. Tak więc, na przykład kod w BundleConfig.cs wygląda następująco:

using System; 
using System.Web.Optimization; 
using StyleBundle = MyNamespace.CustomStyleBundle; 

public class BundleConfig 
{ 
    public static void RegisterBundles(BundleCollection bundles) 
    { 
     bundles.Add(new StyleBundle("~/Content/themes/base/css") 
      .IncludeDirectory("~/Content/themes/base", "*.css")); 
    } 
} 

Więc co trzeba dodać to:

public class CustomStyleBundle : Bundle 
{ 
    public CustomStyleBundle(string virtualPath, IBundleTransform bundleTransform = null) 
     : base(virtualPath, new IBundleTransform[1] 
      { 
       bundleTransform ?? new CustomCssMinify() 
      }) 
    { 
    } 

    public CustomStyleBundle(string virtualPath, string cdnPath, IBundleTransform bundleTransform = null) 
     : base(virtualPath, cdnPath, new IBundleTransform[1] 
      { 
       bundleTransform ?? new CustomCssMinify() 
      }) 
    { 
    } 
} 

public class CustomCssMinify : IBundleTransform 
{ 
    private const string CssContentType = "text/css"; 

    static CustomCssMinify() 
    { 
    } 

    public virtual void Process(BundleContext context, BundleResponse response) 
    { 
     if (context == null) 
      throw new ArgumentNullException("context"); 
     if (response == null) 
      throw new ArgumentNullException("response"); 
     if (!context.EnableInstrumentation) 
     { 
      var minifier = new Minifier(); 
      FixCustomCssErrors(response); 
      string str = minifier.MinifyStyleSheet(response.Content, new CssSettings() 
      { 
       CommentMode = CssComment.None 
      }); 
      if (minifier.ErrorList.Count > 0) 
       GenerateErrorResponse(response, minifier.ErrorList); 
      else 
       response.Content = str; 
     } 
     response.ContentType = CssContentType; 
    } 

    /// <summary> 
    /// Add some extra fixes here 
    /// </summary> 
    /// <param name="response">BundleResponse</param> 
    private void FixCustomCssErrors(BundleResponse response) 
    { 
     response.Content = Regex.Replace(response.Content, @"@import[\s]+([^\r\n]*)[\;]", String.Empty, RegexOptions.IgnoreCase | RegexOptions.Multiline); 
    } 

    private static void GenerateErrorResponse(BundleResponse bundle, IEnumerable<object> errors) 
    { 
     StringBuilder stringBuilder = new StringBuilder(); 
     stringBuilder.Append("/* "); 
     stringBuilder.Append("CSS Minify Error").Append("\r\n"); 
     foreach (object obj in errors) 
      stringBuilder.Append(obj.ToString()).Append("\r\n"); 
     stringBuilder.Append(" */\r\n"); 
     stringBuilder.Append(bundle.Content); 
     bundle.Content = stringBuilder.ToString(); 
    } 
} 

A jeśli potrzebujesz trochę więcej naprawia/błędy można rozszerzyć tę logikę w Metoda FixCustomCssErrors.

+3

To rozwiązanie skutecznie usuwa wszystkie '@ import' z plików, prawda? To prawdopodobnie nie sprawi, że strona będzie wyglądała bardzo dobrze. – MEMark

+1

Nie odnosi się również do faktu, że nie tylko zawiedzie on na @import, ale także na @ -webkit-keyframes i innych doskonale działających CSS, których nie rozpoznaje. Bezużyteczny. W międzyczasie Flash rozwiązał to dekadę temu, dostarczając pojedynczy plik SWF, który był nawet skompresowany. Próbowałem stworzyć pionowo zawiniętą kolumnę w HTML (inny "Święty Graal", ponieważ tak trudno jest zrobić coś tak prostego), tylko po to, aby dowiedzieć się, że chociaż CSS kolumny "liczenia" został zdefiniowany w 2001 roku, to jest rok 2015 i wciąż jest tylko w połowie wdrożone w Chrome. Flexbox też jest do bani, co wymaga pracy z predefiniowaną wysokością. – Triynko

+0

której wersji Bundler używasz? Mam VS 2015 z [Microsoft ASP.NET Web Optimization 1.1.3] (https://www.nuget.org/packages/Microsoft.AspNet.Web.Optimization/1.1.3). Nie mam żadnych błędów w '@ -webkit-keyframes' i widzę to w wyjściu buundle'a. –

Powiązane problemy