Bundler non inclusi i file .min


261

Ho uno strano problema con il bundler mvc4 che non include i file con estensione .min.js

Nella mia classe BundleConfig, dichiaro

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

A mio avviso, dichiaro

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

E quando viene eseguito il rendering, esegue solo il rendering

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

Se rinomino jquery.tmpl.min.js in jquery.tmpl.js (e aggiorno il percorso nel pacchetto di conseguenza), entrambi gli script vengono visualizzati correttamente.

C'è qualche impostazione di configurazione che sta causando che ignora i file '.min.js'?


Sto usando il bundler MVC 4 e include i file .min.js.
Eric J.

la versione RTM o RC? stava funzionando bene anche nel RC
Fatal

10
L'idea è che lavorando in modalità debug, che verrà utilizzata la versione "dev" senza minimizzazione e che quando si è in modalità non debug, venga scelta la versione minimizzata. Per vederlo in azione, cambia il valore di debug web.config da true a false.
Pieter Germishuys,

28
in alcuni casi, tuttavia, non si dispone della versione non ridotta dello script. Potrei forse capirlo se entrambi i file esistessero.
Fatale

1
È un peccato che funzioni in questo modo per impostazione predefinita ... certo, il file potrebbe già essere minimizzato , ma penso che Microsoft non abbia visto il vantaggio di aggiungere script pre-minimizzati ai bundle per scopi di busting della cache (il bel piccolo vparametro hash che viene aggiunto all'URL e cambia quando cambia il contenuto del file)
nulla è necessario il

Risposte:


257

La soluzione che ho pubblicato inizialmente è discutibile (è un trucco sporco). Il comportamento ottimizzato è cambiato nel pacchetto Microsoft.AspNet.Web.Optimization e il tweak non funziona più, come sottolineato da molti commentatori. In questo momento non riesco a riprodurre il problema con la versione 1.1.3 del pacchetto.

Consulta le fonti di System.Web.Optimization.BundleCollection (puoi usare dotPeek per esempio) per una migliore comprensione di ciò che stai per fare. Leggi anche la risposta di Max Shmelev .

Risposta originale :

Rinominare .min.js in .js o fare qualcosa del genere

    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
     }

4
Grazie anche a me - quindi aggiungendo questo alla mia lista gotcha MVC4 :)
Dan B

27
questo è stato un lungo momento, avrebbero potuto aggiungere quei file min commentati con la ragione o qualcosa del risultato, ora un'intera ora ha perso chiedendosi chi stia rubando i miei file di script dall'output.
Giedrius,

5
Secondo il commento di Fatal nel PO, questa soluzione finirà per ridimensionare i riferimenti duplicati sia per la versione ridotta che per quella normale se entrambe esistono (ad es. Jquery).
danmiser,

11
M $, quando viene specificato in modo esplicito somefile.min.js o quando esiste solo il file .min.js, includere solo il file .min.js! Altrimenti basta applicare il comportamento attuale!
Adaptabi

3
Incredibile che la classe attuale si chiami "IgnoreList", ma deriva direttamente da Object. Nessun LINQ, nessuna iterazione. - msdn.microsoft.com/en-us/library/…
JP ten Berge

176

Microsoft implica il seguente comportamento (e preferisco seguirlo nei miei progetti):

versione breve

  1. Hai entrambe le versioni debug e minimizzata di uno script nel tuo progetto nella stessa cartella:
    • script.js
    • script.min.js
  2. Aggiungi solo script.js a un pacchetto nel tuo codice.

Come risultato avrete automaticamente avere le script.js inclusi nel DEBUG modalità e script.min.js in RELEASE modalità.

versione lunga

Puoi avere anche la versione .debug.js . In tal caso il file è incluso nella seguente priorità in DEBUG:

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

in STAMPA:

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

Nota

E comunque, l'unico motivo per avere una versione .min dei tuoi script in MVC4 è il caso in cui la versione minimizzata non può essere elaborata automaticamente. Ad esempio il seguente codice non può essere offuscato automaticamente:

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

In tutti gli altri casi puoi scegliere solo una versione di debug del tuo script.


6
bella spiegazione, tuttavia, il problema del PO era che alcuni script ( jquery.tmpl) non avevano, non venivano, non venivano scaricati la versione non min del file. Il bundler ignora del tutto i file di script se non ha una versione non min in modalità debug
Eonasdan,

D'accordo, bella spiegazione ma non risponde a tutte le domande di OP.
Diego,

2
La versione breve non ha funzionato per me. "script.js" verrebbe incluso in entrambi questi tipi di versioni. Ho attivato DEBUG / RELEASE e (quando ho guardato la fonte) "script.js" era quello selezionato / reso.
user981375

4
user981375, devi anche impostare <compilation debug = "false" /> nel file web.config
Max Shmelev

5
Preferisco questa risposta perché è un approccio "best practice" e spiega come seguire le regole predefinite del bundler per raggiungere lo stesso obiettivo.
James Reategui,

5

Se hai solo una versione ridotta di un file, la soluzione più semplice che ho trovato è quella di copiare il file minimizzato, rimuovere .min dal nome del file copiato, quindi fare riferimento al nome del file non minimizzato nel tuo bundle.

Ad esempio, supponiamo che tu abbia acquistato un componente js e ti abbiano dato un file chiamato some-lib-3.2.1.min.js. Per utilizzare questo file in un bundle, procedi come segue:

  1. Copia some-lib-3.2.1.min.js e rinomina il file copiato in some-lib-3.2.1.js. Includi entrambi i file nel tuo progetto.

  2. Fai riferimento al file non minimizzato nel tuo bundle, in questo modo:

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

Solo perché il file senza 'min' nel nome è effettivamente minimizzato non dovrebbe causare alcun problema (a parte il fatto che è essenzialmente illeggibile). Viene utilizzato solo in modalità debug e viene scritto come uno script separato. Quando non è in modalità debug, il file minimo precompilato deve essere incluso nel pacchetto.


4

Ho trovato una buona soluzione che funziona almeno in MVC5, puoi semplicemente usare Bundleinvece di ScriptBundle. Non ha il comportamento intelligente di ScriptBundlequello che non ci piace (ignorando .min, ecc.) In questo caso. Nella mia soluzione utilizzo Bundleper gli script di parti 3d con file .min e .map e utilizzo ScriptBundleper il nostro codice. Non ho notato alcun inconveniente nel farlo. Per farlo funzionare in questo modo dovrai aggiungere il file originale, ad esempio angular.js, e caricherà angular.js in debug e raggrupperà angular.min.js in modalità di rilascio.


Non sembra funzionare quando le ottimizzazioni sono disabilitate ( ScriptTable.EnableOptimizations = false). I percorsi di script che contengono un modello non vengono visualizzati (ad es ~/Scripts/thirdpartylib/*.js.). Si fa lavoro quando EnableOptimizations = true, ma lo fa ScriptBundle.
Steven Liekens,

Lo uso anche con false (durante lo sviluppo) e non ho problemi che descrivi, quindi potrebbe essere qualcos'altro che ti sta influenzando. Devi anche includere IncludeDirectory invece di include affinché il pattern funzioni.
Ilya Chernomordik,

Sei sicuro che stia eseguendo il rendering della versione ".min.js" del tuo file? Stai usando bundle dallo spazio dei nomi System.Web.Optimizationso dal pacchetto nuget Microsoft.Web.Optimizations?
Steven Liekens,

Uso System.Web.Optimization e ho verificato che esegua il rendering della versione minima, ma ho capito che in realtà non uso IncludiDirectory, ma sarebbe strano se non funzionasse con la versione minima però ... Poiché IncludiDirectory non è abbastanza per me faccio una scansione personalizzata e aggiungo tutto il filtro usando Include, quindi potrebbe essere che il pattern e IncludeDirectory non funzionino correttamente lì, anche se è un po 'strano.
Ilya Chernomordik,

1
No, il problema è duplice: .min.jsesiste solo un file e il *.jsmodello non corrisponde ai file che terminano .min.js.
Steven Liekens,

3

Per eseguire il rendering dei *.min.jsfile, è necessario disabilitare BundleTable.EnableOptimizations, che è un'impostazione globale che si applica a tutti i bundle.

Se si desidera abilitare le ottimizzazioni solo per pacchetti specifici, è possibile creare il proprio ScriptBundletipo che abilita temporaneamente le ottimizzazioni durante l'enumerazione dei file nel pacchetto.

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

Utilizzare OptimizedScriptBundleanziché ScriptBundleper i bundle il cui file minimizzato deve essere sempre utilizzato, indipendentemente dal fatto che esista un file non minimizzato.

Esempio per l'interfaccia utente di Kendo per ASP.NET MVC, che è distribuito come una raccolta di soli file minimizzati.

bundles.Add(new OptimizedScriptBundle("~/bundles/kendo")
        .Include(
            "~/Scripts/kendo/kendo.all.*",
            "~/Scripts/kendo/kendo.aspnetmvc.*",
            "~/Scripts/kendo/cultures/kendo.*",
            "~/Scripts/kendo/messages/kendo.*"));

Mi sono imbattuto in alcuni script mancanti in un'azione di pubblicazione di produzione, e pensando che fosse un problema di MVC, ho trovato questa risposta ... ecco, il kendo è coinvolto. Avendo lavorato troppo a lungo, faccio di tutto per allontanarmi dal kendo
Felipe,

@Felipe Ero nella stessa situazione ed è per questo che ho scritto questa risposta. Il kendo è orribile. Spero che il mio esempio sia utile.
Steven Liekens,

2

Nel mio caso, stavo usando la libreria (meravigliosa!) Knockout.js che viene fornita come versioni Debug / Non:

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

Per farlo funzionare, ho incluso "Knockout- {Version} .js" (non debug) nel mio pacchetto e ho ottenuto il file .debug. file js in modalità debug.


1

Un modo semplice per rinominare il file .min, ad esempio, hai abc.min.css piuttosto che rinominare questo file in abc_min.css e aggiungerlo al tuo bundle. So che non è il modo giusto per farlo, ma solo una soluzione temporanea. grazie e buona programmazione.


1
Ogni volta che nuget scarica il file, è necessario rinominarlo.
Anirudha Gupta,

So che non è il modo giusto per farlo, ma solo una soluzione temporanea
RK Sharma

1
metti che questa linea funziona per me // BundleTable.EnableOptimizations = true;
Anirudha Gupta,

0

Bundler ha molti vantaggi controlla questa pagina MA :

La piattaforma Microsoft MVC4 ritiene che tu abbia almeno una versione ridotta e una versione non ridotta per ogni pacchetto di script o stile (sono disponibili anche altri file come Debug e vsdoc). Quindi abbiamo problemi in situazioni in cui esiste solo uno di questi file.

È possibile modificare lo stato di debug nel file web.config in modo permanente per gestire l'output:

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

Vedi le modifiche all'output! Filtro file modificato. Per raggiungere lo scopo dobbiamo cambiare ignora il filtraggio dei casi che cambierà la logica dell'applicazione!


1
L'aggiunta di debug = "false" non funziona ancora per me. I file min.js non sono ancora inclusi anche se pulisco anche IgnoreList ...
MoSs

-21

Gente, lo terrei semplicemente finché Microsoft non lo farà agire insieme

Prova questo

In RegisterBundles crea questo pacchetto per 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"
 ));

In _Layout.cshtml inserisci questo:

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

In questo modo otteniamo il meglio dei bundle in Production e un riferimento in Debug

Risolvilo quando Microsoft corregge il proprio codice MVC 4


3
Non sono affatto un fan di questa soluzione proposta. Ora devi mantenere il set di script in (almeno) due posizioni
fatale l'

Questo praticamente vanifica lo scopo del raggruppamento, non credi?
Oliver,

4
Il raggruppamento funziona già in questo modo. Se si esegue il progetto in modalità debug, ogni file CSS viene caricato singolarmente, tuttavia quando si esegue in versione vengono combinati e minimizzati in uno. Il codice all'interno del blocco if è identico a ciò che viene visualizzato automaticamente nella pagina in modalità debug.
Chad Levy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.