Bundler ohne .min-Dateien

261

Ich habe ein seltsames Problem mit dem mvc4-Bundler, der keine Dateien mit der Erweiterung .min.js enthält

In meiner BundleConfig-Klasse deklariere ich

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"));            
}

Meiner Ansicht nach erkläre ich

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

Und wenn es rendert, rendert es nur

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

Wenn ich jquery.tmpl.min.js in jquery.tmpl.js umbenenne (und den Pfad im Bundle entsprechend aktualisiere), werden beide Skripte korrekt gerendert.

Gibt es eine Konfigurationseinstellung, die dazu führt, dass '.min.js'-Dateien ignoriert werden?

Tödlich
quelle
Ich verwende MVC 4 Bundler und es enthält .min.js Dateien.
Eric J.
die RTM-Version oder die RC? es funktionierte auch im RC in Ordnung für mich
Fatal
10
Die Idee ist, dass im Debug-Modus die "dev" -Version ohne Minimierung verwendet wird und im Minimierungsmodus die minimierte Version ausgewählt wird. Um es in Aktion zu sehen, ändern Sie Ihren Debug-Wert für web.config von true in false.
Pieter Germishuys
28
In einigen Fällen verfügen Sie jedoch nicht über die nicht minimierte Version des Skripts. Ich könnte es möglicherweise verstehen, wenn beide Dateien existieren.
Tödlicher
1
Es ist ein Mist, dass es standardmäßig so funktioniert ... sicher, die Datei ist möglicherweise bereits minimiert , aber ich denke, Microsoft hat den Vorteil des Hinzufügens vorminimierter Skripte zu Bundles für Cache-Busting-Zwecke nicht erkannt (der nette kleine vParameter-Hash das wird der URL hinzugefügt und ändert sich, wenn sich der Dateiinhalt ändert)
nichts ist

Antworten:

257

Die Lösung, die ich ursprünglich gepostet habe, ist fraglich (ist ein schmutziger Hack). Das optimierte Verhalten hat sich im Microsoft.AspNet.Web.Optimization-Paket geändert, und die Optimierung funktioniert nicht mehr, wie viele Kommentatoren betonten. Im Moment kann ich das Problem mit der Version 1.1.3 des Pakets überhaupt nicht reproduzieren.

Weitere Informationen zu Ihren Aktivitäten finden Sie in den Quellen zu System.Web.Optimization.BundleCollection (Sie können beispielsweise dotPeek verwenden ). Lesen Sie auch die Antwort von Max Shmelev .

Ursprüngliche Antwort :

Benennen Sie .min.js entweder in .js um oder tun Sie etwas Ähnliches

    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
quelle
4
Danke auch von mir - also füge dies meiner MVC4 Gotcha-Liste hinzu :)
Dan B
27
Dies war ein langer Moment, sie hätten diese Min-Dateien hinzufügen können, die mit Grund oder etwas Kommentiertem auskommentiert wurden. Jetzt wurde eine ganze Stunde damit verbracht, sich zu fragen, wer meine Skriptdateien aus der Ausgabe stiehlt.
Giedrius
5
Gemäß dem Kommentar von Fatal im OP führt diese Lösung dazu, dass doppelte Referenzen sowohl für die minimierte als auch für die reguläre Version wiederhergestellt werden, wenn beide vorhanden sind (z. B. jquery).
Danmiser
11
M $, wenn somefile.min.js explizit angegeben ist oder wenn nur die .min.js-Datei vorhanden ist, dann nur die .min.js-Datei einschließen! Ansonsten einfach das aktuelle Verhalten anwenden!
Adaptabi
3
Unglaublich, dass die eigentliche Klasse "IgnoreList" heißt, aber direkt von Object abgeleitet ist. Kein LINQ, keine Iteration. - msdn.microsoft.com/en-us/library/…
JP ten Berge
176

Microsoft impliziert das folgende Verhalten (und ich ziehe es vor, es in meinen Projekten zu befolgen):

Kurzversion

  1. Sie haben sowohl Debug- als auch minimierte Versionen eines Skripts in Ihrem Projekt unter demselben Ordner:
    • script.js
    • script.min.js
  2. Sie fügen einem Bundle in Ihrem Code nur script.js hinzu .

Infolgedessen werden die Datei script.js automatisch im DEBUG- Modus und die Datei script.min.js im RELEASE- Modus angezeigt .

lange Version

Sie können auch die Version .debug.js haben . In diesem Fall ist die Datei in DEBUG in der folgenden Priorität enthalten:

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

in RELEASE:

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

Hinweis

Übrigens ist der einzige Grund, eine .min- Version Ihrer Skripte in MVC4 zu haben, der Fall, wenn die minimierte Version nicht automatisch verarbeitet werden kann. Beispielsweise kann der folgende Code nicht automatisch verschleiert werden:

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

In allen anderen Fällen können Sie nur eine Debug-Version Ihres Skripts verwenden.

Max Shmelev
quelle
6
Eine nette Erklärung war jedoch, dass das Problem des OP darin bestand, dass einige Skripte ( jquery.tmpl) die Nicht-Min-Version der Datei nicht haben, nicht mitgeliefert wurden und nicht heruntergeladen wurden. Der Bundler ignoriert die Skriptdateien vollständig, wenn er keine Nicht-Min-Version im Debug-Modus hat
Eonasdan
Stimme zu, nette Erklärung, aber sie beantwortet die Frage von OP überhaupt nicht.
Diego
2
Die Kurzversion hat bei mir nicht funktioniert. "script.js" wäre in beiden Release-Typen enthalten. Ich habe DEBUG / RELEASE umgeschaltet und (als ich mir die Quelle angesehen habe) 'script.js' wurde ausgewählt / gerendert.
user981375
4
user981375, müssen Sie auch <compilation debug = "false" /> in der Datei web.config setzen
Max Shmelev
5
Ich bevorzuge diese Antwort, da es sich um einen "Best Practices" -Ansatz handelt und erklärt, wie die Standardregeln des Bundlers befolgt werden können, um dasselbe Ziel zu erreichen.
James Reategui
5

Wenn Sie nur eine verkleinerte Version einer Datei haben, besteht die einfachste Lösung darin, die minimierte Datei zu kopieren, .min aus dem Namen der kopierten Datei zu entfernen und dann auf den nicht minimierten Dateinamen in Ihrem Bundle zu verweisen.

Angenommen, Sie haben eine js-Komponente gekauft und eine Datei mit dem Namen some-lib-3.2.1.min.js erhalten. Gehen Sie wie folgt vor, um diese Datei in einem Bundle zu verwenden:

  1. Kopieren Sie some-lib-3.2.1.min.js und benennen Sie die kopierte Datei in some-lib-3.2.1.js um. Fügen Sie beide Dateien in Ihr Projekt ein.

  2. Verweisen Sie wie folgt auf die nicht minimierte Datei in Ihrem Bundle:

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

Nur weil die Datei ohne 'min' im Namen tatsächlich minimiert ist, sollte dies keine Probleme verursachen (außer der Tatsache, dass sie im Wesentlichen nicht lesbar ist). Es wird nur im Debug-Modus verwendet und als separates Skript geschrieben. Wenn Sie sich nicht im Debug-Modus befinden, sollte die vorkompilierte min-Datei in Ihrem Bundle enthalten sein.

Joelfp
quelle
4

Ich habe eine gute Lösung gefunden, die zumindest in MVC5 funktioniert. Sie können sie einfach Bundleanstelle von verwenden ScriptBundle. Es hat nicht das kluge Verhalten ScriptBundle, das wir in diesem Fall nicht mögen (.min ignorieren usw.). In meiner Lösung verwende ich Bundlefür 3D-Party-Skripte mit .min- und .map-Dateien und verwende sie ScriptBundlefür unseren Code. Ich habe keine Nachteile dabei bemerkt. Damit es auf diese Weise funktioniert, müssen Sie die Originaldatei hinzufügen, z. B. angular.js, und es wird angular.js im Debug geladen und die angle.min.js im Release-Modus gebündelt.

Ilya Chernomordik
quelle
Es scheint nicht zu funktionieren, wenn Optimierungen deaktiviert sind ( ScriptTable.EnableOptimizations = false). Skriptpfade, die ein Muster enthalten, werden nicht gerendert (z ~/Scripts/thirdpartylib/*.js. B. ). Es funktioniert wann EnableOptimizations = true, aber auch ScriptBundle.
Steven Liekens
Ich verwende es auch mit false (während der Entwicklung) und habe keine Probleme, die Sie beschreiben. Daher könnte es etwas anderes sein, das sich auf Sie auswirkt. Sie müssen auch IncludeDirectory ausführen, anstatt include, damit das Muster funktioniert.
Ilya Chernomordik
Sind Sie sicher, dass die Version ".min.js" Ihrer Datei gerendert wird? Verwenden Sie Bundles aus dem Namespace System.Web.Optimizationsoder aus dem Nuget-Paket Microsoft.Web.Optimizations?
Steven Liekens
Ich verwende System.Web.Optimization und habe überprüft, ob es die Min-Version rendert, aber ich habe herausgefunden, dass ich IncludeDirectory tatsächlich nicht verwende, aber es wäre seltsam, wenn dies nicht mit der Min-Version funktionieren würde ... Wie IncludeDirectory nicht genug für mich Ich mache einen benutzerdefinierten Scan und füge den gesamten Filter mit Include hinzu, so dass das Muster und IncludeDirectory dort möglicherweise nicht richtig funktionieren, obwohl es etwas seltsam ist.
Ilya Chernomordik
1
Nein, das Problem ist zweifach: Es ist nur eine .min.jsDatei vorhanden, und das *.jsMuster stimmt nicht mit Dateien überein, die auf enden .min.js.
Steven Liekens
3

Um *.min.jsDateien zu rendern , müssen Sie deaktivieren. Dies BundleTable.EnableOptimizationsist eine globale Einstellung, die für alle Bundles gilt.

Wenn Sie Optimierungen nur für bestimmte Bundles aktivieren möchten, können Sie einen eigenen ScriptBundleTyp erstellen , der vorübergehend Optimierungen beim Auflisten von Dateien im Bundle aktiviert .

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;
        }
    }
}

Verwendung OptimizedScriptBundleanstelle von ScriptBundlefür Bundles, deren minimierte Datei immer verwendet werden sollte, unabhängig davon, ob eine nicht minimierte Datei vorhanden ist.

Beispiel für die Kendo-Benutzeroberfläche für ASP.NET MVC, die als Sammlung nur minimierter Dateien verteilt wird.

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
quelle
Ich bin auf einige fehlende Skripte in einer Produktionsveröffentlichungsaktion gestoßen und dachte, es sei ein MVC-Problem. Ich habe diese Antwort gefunden. Und siehe da, Kendo ist involviert. Nachdem ich zu lange damit gearbeitet habe, tue ich alles, um von Kendo wegzukommen
Felipe
@Felipe Ich war in der gleichen Situation, weshalb ich diese Antwort geschrieben habe. Kendo ist schrecklich. Ich hoffe mein Beispiel ist hilfreich.
Steven Liekens
2

Für meinen Fall habe ich die (wundervolle!) Knockout.js-Bibliothek verwendet, die als Debug / Non-Version erhältlich ist:

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

Damit dies funktioniert, habe ich "Knockout- {Version} .js" (ohne Debug) in mein Bundle aufgenommen und den .debug erhalten. js-Datei im Debug-Modus.

AcidPAT
quelle
1

Eine einfache Möglichkeit, einfach die .min-Datei umzubenennen, zum Beispiel abc.min.css, als diese Datei einfach in abc_min.css umzubenennen und diese Ihrem Bundle hinzuzufügen. Ich weiß, dass dies nicht der richtige Weg ist, sondern nur eine vorübergehende Lösung. Danke und viel Spaß beim Codieren.

RK Sharma
quelle
1
Jedes Mal, wenn nuget die Datei herunterlädt, müssen Sie sie dann umbenennen.
Anirudha Gupta
Ich weiß, es ist nicht der richtige Weg, es zu tun, sondern nur eine vorübergehende Lösung
RK Sharma
1
Setzen Sie diese Zeile arbeiten für mich // BundleTable.EnableOptimizations = true;
Anirudha Gupta
0

Bundler haben viele Vorteile überprüfen Sie diese Seite ABER :

Die Microsoft MVC4-Plattform berücksichtigt, dass Sie für jedes Skript oder Style-Bundle mindestens eine minimierte und eine nicht minimierte Version haben (andere Dateien wie Debug und vsdoc sind ebenfalls verfügbar). Wir haben also Probleme in Situationen, in denen es nur eine dieser Dateien gibt.

Sie können den Debug-Status in der Datei web.config dauerhaft ändern, um die Ausgabe zu verarbeiten:

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

Siehe die Ausgabeänderungen! Dateifilterung geändert. Um diesen Zweck zu erfüllen, müssen wir die Filterung für ignorierte Fälle ändern, wodurch sich die Anwendungslogik ändert!

Amirhossein Mehrvarzi
quelle
1
Das Hinzufügen von debug = "false" funktioniert bei mir immer noch nicht. min.js Dateien sind immer noch nicht enthalten, obwohl ich auch die IgnoreList lösche ...
MoSs
-21

Leute, ich würde es einfach so lange behalten, bis Microsoft es zusammenbringt

Versuche dies

In RegisterBundles erstellen Sie dieses Bundle für 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"
 ));

Geben Sie in _Layout.cshtml Folgendes ein:

@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")   
 }

Auf diese Weise erhalten wir die besten Bundles in der Produktion und eine Referenz in Debug

Beheben Sie das Problem, wenn Microsoft den MVC 4-Code korrigiert

user1819794
quelle
3
Ich bin überhaupt kein Fan dieser vorgeschlagenen Lösung. Sie müssen jetzt die Skripte an (mindestens) zwei Stellen verwalten
Fatal
Das macht den Zweck der Bündelung ziemlich zunichte, meinst du nicht auch?
Oliver
4
Die Bündelung funktioniert bereits so. Wenn Sie das Projekt im Debug-Modus ausführen, wird jede CSS-Datei einzeln geladen. Wenn Sie sie jedoch in der Version ausführen, werden sie kombiniert und zu einer minimiert. Der Code im if-Block ist identisch mit dem, was im Debug-Modus automatisch auf der Seite gerendert wird.
Chad Levy