Bundler nie obejmuje plików .min

261

Mam dziwny problem z pakietem mvc4, który nie zawiera plików z rozszerzeniem .min.js

W mojej klasie BundleConfig deklaruję

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/Scripts/jquery")
        .Include("~/Scripts/jquery-1.8.0.js")
        .Include("~/Scripts/jquery.tmpl.min.js"));            
}

Moim zdaniem oświadczam

<html>
    <head>
    @Scripts.Render("~/Scripts/jquery")
    </head><body>test</body>
</html>

A kiedy renderuje, renderuje tylko

<html>
    <head>
         <script src="/Scripts/jquery-1.8.0.js"></script>
    </head>
    <body>test</body>
</html>

Jeśli zmienię nazwę pliku jquery.tmpl.min.js na jquery.tmpl.js (i odpowiednio zaktualizuję ścieżkę w pakiecie), oba skrypty są renderowane poprawnie.

Czy jest jakieś ustawienie konfiguracji, które powoduje, że ignoruje pliki „.min.js”?

Fatalny
źródło
Korzystam z programu pakującego MVC 4 i zawiera on pliki .min.js.
Eric J.,
wersja RTM czy RC? dla mnie również działało w RC
Fatal
10
Chodzi o to, że pracując w trybie debugowania, będzie używana wersja „dev” bez minimalizacji, a gdy jesteś w trybie innym niż debugowanie, wybierana jest wersja zminimalizowana. Aby zobaczyć to w akcji, zmień wartość debugowania pliku web.config z prawdy na fałsz.
Pieter Germishuys,
28
w niektórych przypadkach nie masz nie zminimalizowanej wersji skryptu. Mógłbym ewentualnie zrozumieć, gdyby istniały oba pliki.
Fatal
1
Jest to błąd, że domyślnie działa w ten sposób ... pewnie, plik może być już zminimalizowany , ale myślę, że Microsoft nie dostrzegł korzyści z dodania wstępnie zminimalizowanych skryptów do pakietów w celu pomijania pamięci podręcznej (fajny mały vparametr skrótu który jest dodawany do
adresu

Odpowiedzi:

257

Rozwiązanie, które pierwotnie opublikowałem, jest wątpliwe (to brudny hack). Poprawione zachowanie zmieniło się w pakiecie Microsoft.AspNet.Web.Optimization, a poprawka już nie działa, jak zauważyło wielu komentatorów. W tej chwili nie mogę odtworzyć problemu w wersji 1.1.3 pakietu.

Zobacz źródła System.Web.Optimization.BundleCollection (możesz na przykład użyć dotPeek ), aby lepiej zrozumieć, co zamierzasz zrobić. Przeczytaj także odpowiedź Maxa Shmeleva .

Oryginalna odpowiedź :

Zmień nazwę pliku .min.js na .js lub zrób coś takiego

    public static void AddDefaultIgnorePatterns(IgnoreList ignoreList)
    {
        if (ignoreList == null)
            throw new ArgumentNullException("ignoreList");
        ignoreList.Ignore("*.intellisense.js");
        ignoreList.Ignore("*-vsdoc.js");
        ignoreList.Ignore("*.debug.js", OptimizationMode.WhenEnabled);
        //ignoreList.Ignore("*.min.js", OptimizationMode.WhenDisabled);
        ignoreList.Ignore("*.min.css", OptimizationMode.WhenDisabled);
    }

    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.IgnoreList.Clear();
        AddDefaultIgnorePatterns(bundles.IgnoreList);
        //NOTE: it's bundles.DirectoryFilter in Microsoft.AspNet.Web.Optimization.1.1.3 and not bundles.IgnoreList

        //...your code
     }
Pavel
źródło
4
Dziękuję też ode mnie - dodając to do mojej listy gotcha MVC4 :)
Dan B
27
to był długi moment wtf. Mogli oni dodawać te minimalne pliki skomentowane z uzasadnieniem lub czymś, co miało wynik, teraz cała godzina zmarnowała zastanawianie się, kto kradnie moje pliki skryptowe z wyjścia.
Giedrius
5
Zgodnie z komentarzem Fatala w PO, to rozwiązanie spowoduje, że powtórzą się duplikaty referencji zarówno dla wersji zminimalizowanej, jak i zwykłej, jeśli obie istnieją (np. Jquery).
danmiser
11
M $, jeśli jawnie określono plik somefile.min.js lub gdy istnieje tylko plik .min.js, wówczas dołącz tylko plik .min.js! W przeciwnym razie po prostu zastosuj bieżące zachowanie!
Adaptabi,
3
Niesamowite, że rzeczywista klasa nazywa się „IgnoreList”, a jednak wywodzi się bezpośrednio z Object. Bez LINQ, bez iteracji. - msdn.microsoft.com/en-us/library/…
JP ten Berge
176

Microsoft sugeruje następujące zachowanie (i wolę je stosować w moich projektach):

krótka wersja

  1. Masz zarówno debugowanie, jak i zminimalizowane wersje skryptu w swoim projekcie w tym samym folderze:
    • script.js
    • script.min.js
  2. Do pakietu dodajesz tylko skrypt.js .

W rezultacie będzie automatycznie mają script.js zawarte w DEBUG MODE i script.min.js w ZWOLNIENIE trybie.

długa wersja

Możesz mieć także wersję .debug.js . W takim przypadku plik jest objęty następującym priorytetem w DEBUG:

  1. skrypt.debug.js
  2. script.js

W WYDANIU:

  1. script.min.js
  2. script.js

Uwaga

Nawiasem mówiąc, jedynym powodem posiadania wersji .min twoich skryptów w MVC4 jest przypadek, w którym zminimalizowana wersja nie może być przetwarzana automatycznie. Na przykład następujący kod nie może być zaciemniony automatycznie:

if (DEBUG) console.log("Debug message");

We wszystkich innych przypadkach możesz użyć tylko debugowanej wersji skryptu.

Max Shmelev
źródło
6
fajne wyjaśnienie, jednak problemem OP było to, że niektóre skrypty ( jquery.tmpl) nie miały, nie były dostarczane, nie pobierały nie-minimalnej wersji pliku. Program pakujący całkowicie ignoruje pliki skryptów, jeśli nie ma wersji innej niż minimalna w trybie debugowania
Eonasdan
Zgadzam się, miłe wyjaśnienie, ale nie odpowiada na wszystkie pytania OP.
Diego
2
Krótka wersja nie działała dla mnie. Plik „script.js” byłby zawarty w obu tych typach wydań. Przełączałem DEBUG / RELEASE i (kiedy spojrzałem na źródło) „script.js” był tym wybranym / renderowanym.
user981375,
4
user981375, musisz również ustawić <debugowanie kompilacji = "false" /> w pliku web.config
Max Shmelev
5
Wolę tę odpowiedź, ponieważ jest to podejście oparte na „najlepszych praktykach” i wyjaśnia, w jaki sposób można przestrzegać domyślnych reguł pakietu, aby osiągnąć ten sam cel.
James Reategui
5

Jeśli masz tylko zminimalizowaną wersję pliku, najprostszym rozwiązaniem, jakie znalazłem, jest skopiowanie zminimalizowanego pliku, usunięcie .min z nazwy skopiowanego pliku, a następnie odwołanie się do niezminifikowanej nazwy pliku w pakiecie.

Załóżmy na przykład, że kupiłeś komponent js i dali ci plik o nazwie some-lib-3.2.1.min.js. Aby użyć tego pliku w pakiecie, wykonaj następujące czynności:

  1. Skopiuj plik some-lib-3.2.1.min.js i zmień nazwę skopiowanego pliku na some-lib-3.2.1.js. Dołącz oba pliki do swojego projektu.

  2. Odwołaj się do niezminimalizowanego pliku w pakiecie, tak jak to:

    bundles.Add(new ScriptBundle("~/bundles/libraries").Include(
        "~/Scripts/some-lib-{version}.js"
    ));

Tylko dlatego, że plik bez „min” w nazwie jest faktycznie zmniejszony, nie powinien powodować żadnych problemów (poza tym, że jest zasadniczo nieczytelny). Jest używany tylko w trybie debugowania i jest zapisywany jako osobny skrypt. Gdy nie jest w trybie debugowania, skompilowany plik min powinien zostać dołączony do pakietu.

joelfp
źródło
4

Znalazłem dobre rozwiązanie, które działa przynajmniej w MVC5, którego możesz użyć Bundlezamiast ScriptBundle. W tym przypadku nie ma inteligentnego zachowania ScriptBundle, którego nie lubimy (ignorując .min itp.). W moim rozwiązaniu używam Bundleskryptów stron 3D z plikami .min i .map i używam ScriptBundledo naszego kodu. Nie zauważyłem żadnych wad tego. Aby działał w ten sposób, musisz dodać oryginalny plik, np. Angular.js, i załaduje plik angular.js do debugowania, a także spakuje plik angular.min.js w trybie wydania.

Ilya Chernomordik
źródło
Nie działa, gdy optymalizacje są wyłączone ( ScriptTable.EnableOptimizations = false). Ścieżki skryptu zawierające wzorzec nie są renderowane (np ~/Scripts/thirdpartylib/*.js.). Działa , kiedy EnableOptimizations = true, ale tak też jest ScriptBundle.
Steven Liekens,
Używam go również z fałszem (podczas programowania) i nie mam problemów, które opisujesz, więc może to mieć wpływ na coś innego. Musisz także włączyć IncludeDirectory zamiast uwzględnienia, aby wzorzec działał.
Ilya Chernomordik
Czy na pewno wyświetla wersję pliku „.min.js”? Czy używasz pakietów z przestrzeni nazw System.Web.Optimizationslub z pakietu nuget Microsoft.Web.Optimizations?
Steven Liekens,
Używam System.Web.Optimization i sprawdziłem, czy renderuje wersję minimalną, ale doszedłem do wniosku, że tak naprawdę nie używam IncludeDirectory, ale byłoby dziwne, gdyby to nie działało z wersją minimalną ... Ponieważ IncludeDirectory nie jest wystarczy mi wykonać niestandardowe skanowanie i dodać wszystkie filtry za pomocą Include, więc może być tak, że wzorzec i IncludeDirectory nie działają tam poprawnie, choć jest to trochę dziwne.
Ilya Chernomordik
1
Nie, problem jest dwojaki: .min.jsistnieje tylko plik, a *.jswzorzec nie pasuje do plików kończących się na .min.js.
Steven Liekens,
3

Aby renderować *.min.jspliki, musisz je wyłączyć BundleTable.EnableOptimizations, co jest ustawieniem globalnym, które dotyczy wszystkich pakietów.

Jeśli chcesz włączyć optymalizacje tylko dla określonych pakietów, możesz utworzyć własny ScriptBundletyp, który tymczasowo włącza optymalizacje podczas wyliczania plików w pakiecie.

public class OptimizedScriptBundle : ScriptBundle
{
    public OptimizedScriptBundle(string virtualPath)
        : base(virtualPath)
    {
    }

    public OptimizedScriptBundle(string virtualPath, string cdnPath)
        : base(virtualPath, cdnPath)
    {
    }

    public override IEnumerable<BundleFile> EnumerateFiles(BundleContext context)
    {
        if (context.EnableOptimizations)
            return base.EnumerateFiles(context);
        try
        {
            context.EnableOptimizations = true;
            return base.EnumerateFiles(context);
        }
        finally
        {
            context.EnableOptimizations = false;
        }
    }
}

Użyj OptimizedScriptBundlezamiast w ScriptBundleprzypadku pakietów, których zminimalizowany plik powinien być zawsze używany, niezależnie od tego, czy istnieje niezminimalizowany plik.

Przykład Kendo UI dla ASP.NET MVC, który jest dystrybuowany jako zbiór tylko zminimalizowanych plików.

bundles.Add(new OptimizedScriptBundle("~/bundles/kendo")
        .Include(
            "~/Scripts/kendo/kendo.all.*",
            "~/Scripts/kendo/kendo.aspnetmvc.*",
            "~/Scripts/kendo/cultures/kendo.*",
            "~/Scripts/kendo/messages/kendo.*"));
Steven Liekens
źródło
W akcji produkcyjnej natknąłem się na brakujące skrypty i myśląc, że to problem MVC, znalazłem tę odpowiedź. Oto Kendo jest zaangażowane. Pracując z nim zbyt długo, robię wszystko, aby uciec od kendo
Felipe
@Fipe byłem w tej samej sytuacji i dlatego napisałem tę odpowiedź. Kendo jest okropne. Mam nadzieję, że mój przykład jest pomocny.
Steven Liekens
2

W moim przypadku korzystałem z (cudownej!) Biblioteki Knockout.js, która jest dostępna w wersji Debug / Non:

"~/Scripts/knockout-{Version}.js"
"~/Scripts/knockout-{Version}.Debug.js"

Aby to zadziałało, dołączyłem plik „Knockout- {Version} .js” (bez debugowania) do mojego pakietu i dostałem .debug. plik js w trybie debugowania.

AcidPAT
źródło
1

W prosty sposób po prostu zmień nazwę pliku .min, na przykład masz abc.min.css, niż po prostu zmień nazwę tego pliku na abc_min.css i dodaj go do swojego pakietu. Wiem, że nie jest to właściwy sposób, ale tylko tymczasowe rozwiązanie. dzięki i szczęśliwego kodowania.

RK Sharma
źródło
1
Za każdym razem, gdy nuget pobiera plik, musisz zmienić jego nazwę.
Anirudha Gupta
Wiem, że nie jest to właściwy sposób, ale tylko tymczasowe rozwiązanie
RK Sharma
1
wstaw tę linię działają dla mnie // BundleTable.EnableOptimizations = true;
Anirudha Gupta
0

Bundler ma wiele zalet sprawdź tę stronę ALE :

Platforma Microsoft MVC4 uważa, że ​​masz co najmniej zarówno wersję zminimalizowaną, jak i wersję nieuprawnioną dla każdego skryptu lub pakietu stylów (dostępne są również inne pliki, takie jak Debug i vsdoc). Mamy więc problemy w sytuacjach, gdy istnieje tylko jeden z tych plików.

Możesz trwale zmienić stan debugowania w pliku web.config, aby obsłużyć dane wyjściowe:

<compilation debug="false" targetFramework="4.0" />

Zobacz zmiany wyjściowe! Filtrowanie plików zmienione. Aby osiągnąć cel, musimy zmienić ignorowanie filtrowania skrzynek, co zmieni logikę aplikacji!

Amirhossein Mehrvarzi
źródło
1
Dodanie debugowania = „false” nadal nie działa dla mnie. Pliki min.js nadal nie są uwzględniane, mimo że wyczyszczam również listę IgnoreList ...
MoSs
-21

Ludzie trzymałbym to po prostu, dopóki Microsoft nie będzie działać razem

Spróbuj tego

W RegisterBundles utwórz ten pakiet dla Kendo

bundles.Add(new StyleBundle("~/Content/kendo/css").Include(
                    "~/Content/kendo/2012.3.1121/kendo.common.min.css",
                     "~/Content/kendo/2012.3.1121/kendo.dataviz.min.css",
                      "~/Content/kendo/2012.3.1121/kendo.blueopal.min.css"
 ));

W _Layout.cshtml umieść to:

@if (HttpContext.Current.IsDebuggingEnabled)
 { 
<link href="@Url.Content("~/Content/kendo/2012.3.1121/kendo.common.min.css")"      
rel="stylesheet"  type="text/css" />
<link href="@Url.Content("~/Content/kendo/2012.3.1121/kendo.dataviz.min.css")" 
rel="stylesheet" type="text/css" />   
<link href="@Url.Content("~/Content/kendo/2012.3.1121/kendo.blueopal.min.css")"    
rel="stylesheet" type="text/css" />
 }
 else
 {
     @Styles.Render("~/Content/kendo/css")   
 }

W ten sposób otrzymujemy najlepsze pakiety w dziale Produkcja i referencje w Debugowaniu

Napraw to, gdy Microsoft naprawi swój kod MVC 4

użytkownik1819794
źródło
3
W ogóle nie jestem fanem tego proponowanego rozwiązania. Teraz musisz utrzymywać zestaw skryptów w (co najmniej) dwóch miejscach
Fatal
To w dużej mierze przeczy celowi łączenia, nie sądzisz?
Oliver
4
Sprzedaż wiązana działa już w ten sposób. Jeśli uruchomisz projekt w trybie debugowania, każdy plik CSS jest ładowany osobno, jednak po uruchomieniu w wersji są one łączone i dzielone na jeden. Kod w bloku if jest identyczny z tym, co jest renderowane na stronie automatycznie w trybie debugowania.
Chad Levy