19 Gen

Bundling in un progetto ASP.NET MVC

Programming - ASP.NET MVC

Google Translate traduce la parola “bundle”  in “impacchettare”. Niente di più azzeccato per introdurre il bundling in un’applicazione ASP.NET MVC.

Oggi sviluppare siti e applicazioni per il web risulta un’attività estremamente complessa. Esistono svariati moduli open source facilmente integrabili durante lo sviluppo. Si pensi alle migliaia di librerie javascript disponibili (JQuery, Backbone.js, Knockout.js… e chi più ne ha più ne metta) o ai frameworks CSS (tra i quali spiccano Bootstrap e Zurb Foundation).

A questi moduli si aggiungono i tools di supporto allo sviluppo:  generatori di codice (Sass, Less, Coffescript, Handlebars, Jade,…), task manager (ad esempio Grunt, Gulp, Broccoli, Browserify), package manager (Nuget, Npm, Bower, ecc.) e molti altri ancora.

Quando bisogna integrare moduli esterni in un progetto web, gli sviluppatori si affidano a procedure di bundling. Queste ci assistono nell’ottimizzazione del codice.

Tra gli aspetti più importanti del bundling ci sono l’aggregazione e l’ottimizzazione dei diversi sorgenti in un unico file evitando di sovraccaricare le comunicazioni client-server (I/O overhead). Nello sviluppo web, al bundling si associa infatti un processo di “minificazione” con lo scopo di ridurre le dimensioni dei dati scambiati tra le chiamate. Grazie al bundling vengono eliminate le parti superflue o ridondanti di un file, come ad esempio spazi, commenti, ritorni a capo, ecc.

Nei progetti ASP.NET MVC le procedure di bundlig vengono gestite in tre passi:

  1. Configurazione: si istruisce l’applicazione su come combinare e comprimere i file;
  2. Registrazione: si informa l’applicazione dell’esistenza dei bundles;
  3. Reference: si referenziano i bundles nelle View di progetto e quindi nel frontend.

Vediamo nel dettaglio queste tre fasi.

Configurare i bundles

La configurazione dei bundles viene attuata nel file BundleConfig.cs riposto nella cartella  App_Start . La configurazione consiste nel definire e aggiunegere i bundles alla tabella dei bundles.

Nell’esempio qui sotto vengono inclusi tre file javascript  e due fogli di stile:

 
public static void RegisterBundles(BundleCollection bundles)
{
  //Scripts js
  var myBundleScript = new ScriptBundle("~/bundles/main-js");
  myBundleScript.Include(
    "~/Scripts/cls/clsRollingDiv.js",
    "~/Scripts/cls/clsRollingBanner.js",
    "~/Scripts/main-dev.js");

  //Cascade Styles
  var myBundleCss = new StyleBundle("~/bundles/main-css");
  myBundleCss.Include(
    "~/Content/css/css1.js",
    "~/Content/css/css2.js");
  
  //Aggiungo a BundleTable
  bundles.Add(myBundleScript);
  bundles.Add(myBundleCss);
}

Da notare che, a seconda del tipo di file, vengono utilizzate due diverse classi .NET: ScriptBundle per i file javascript e StyleBundle per i fogli di stile.

Il metodo Include  può essere sostituito dal corrispettivo IncludeDirectory che comprenderà tutti i file presenti in una cartella evitando così di elencare i file singolarmente. In entrambi i casi, alla chiamata viene passato il path dei file che si vogliamo impacchettare.

Il simbolo ~ rappresenta la root  di progetto. Questo shortcut risulta comodissimo quando passiamo da un ambiente di sviluppo ad uno di produzione. A titolo di esempio, durante lo sviluppo lo shorcut puo’ indicare una root del tipo http://localhost:1234/js/[files] mentre in produzione i file vengono ricercati in http://www.miosito.it/Scripts/[files]. Questo switch viene gestito autonomamente da ASP.NET.

Registrare i bundles

Terminata la configurazione, si passa alla registrazione dei bundles. Questa avviene nella procedura  Application_Start del file  Global.asax del nostro progetto ASP.NET MVC:

  protected void Application_Start()
    {
      AreaRegistration.RegisterAllAreas();
      [...]
      BundleConfig.RegisterBundles(BundleTable.Bundles);
    }

Con il semplice comando BundleConfig.RegisterBundles tutti i bundles vengono inclusi nella BundleTable e registrati nel progetto.

Referenziare i bundles

L’ultimo step consiste nel referenziare i bundles nelle View del nostro progetto MVC. I bundle devono quindi essere configurati pensando al loro reale utilizzo nel frontend e  nelle pagine web.

Per i file molto utilizzati (come ad esempio le librerie Bootstrap in un progetto responsive) è meglio referenziare i bundle nelle View condivise (Shared). E’ invece preferibile isolare i file meno utilizzati in bundle indipendenti  e richiamali nelle singole View. Nell’esempio sotto, richiamiamo un bundle secondario in una View non condivisa:

    
<!DOCTYPE html>
<html class="no-js" lang="en">
<head>
  <meta charset="utf-8" />
  [...]
  @Styles.Render("~/bundles/secondary-css")
</head>
<body>
  [...]
  @Scripts.Render("~/bundles/secondary-js")
</body>
</html>

Testare il comportamento dei bundles

Ora che abbiano capito come funzionano i bundle,  proviamo a testarne il comportamento. Per il test ipotizziamo di aver creato un bundle per le librerie di JQuery. Lanciamo Visual Studio e analiziamo le chiamate HTTP avvalendoci di Firefox e Firebug.

Notiamo subito che l’ottimizzazione dei file avviene solo quando simuliamo l’ambiente di produzione – quindi col parametro debug=false . Nella figura si nota l’impachettamento e l’ottimizzazione delle librerie JQuery in un ipotetico ambiente di produzione:bundles_jquery_prod

Quando lanciamo il progetto in modalità sviluppo – debug=true –  le librerie vengono restitutite senza alcuna ottimizzazione così da semplificare l’eventuale debugging. E infatti, nell’esempio proposto, viene inoltrato il file originale contenuto nella cartella degli Scripts della nostra applicazione ASP.NET MVC:bundles_jquery_debug

Conclusioni

Una corretta impostazione dei bundle comporta notevoli vantaggi, ovvero:

  1.  Ridurre le chiamate HTTP grazie all’aggregazione dei file;
  2. Ridurre le dimensioni dei file, e quindi il traffico, grazie al processo di “minificazione”;
  3. Caching dei dati inoltrati.

Il caching è particolarmente interessante. In un’applicazione ASP.NET MVC il processo di bundle setta l’header HTTP Expires ad un anno da quando il bundle è stato creato.  Quando si naviga verso una pagina precedentemente visitata non viene quindi inoltrato alcun dato ma vengono utilizzati i dati conservati nella cache del browser.

A livello statistico, Microsoft dichiara notevoli miglioramenti quando si introduce il bundling in un’applicazione:

Uso Con Bundle Senza Bundle Variazione
File Requests 9 34 256%
KB Inviati 3.26 11.92 266%
KB Ricevuti 388.51 530% 36%
Tempo Attesa 510 MS 780 MS 53%
Riferimento: Microsoft ASP.NET Blog

La tabella mostra tutta la convenienza di utilizzare procedure di bundling nelle nostre applicazioni ASP.NET MVC. Buona programmazione!