<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jblog &#187; Ottimizzazione</title>
	<atom:link href="http://jblog.it/category/ottimizzazione/feed" rel="self" type="application/rss+xml" />
	<link>http://jblog.it</link>
	<description>News e appunti per webmaster</description>
	<lastBuildDate>Tue, 25 May 2010 16:16:12 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>20 servizi web e librerie per ottimizzare i componenti della pagina: immagini, javascript, css</title>
		<link>http://jblog.it/2009/06/10/ottimizzare-componenti-pagina-velocizzare-caricamento-immagini-css-script_640.html</link>
		<comments>http://jblog.it/2009/06/10/ottimizzare-componenti-pagina-velocizzare-caricamento-immagini-css-script_640.html#comments</comments>
		<pubDate>Wed, 10 Jun 2009 11:36:50 +0000</pubDate>
		<dc:creator>Giacomo</dc:creator>
				<category><![CDATA[Css]]></category>
		<category><![CDATA[Grafica]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Ottimizzazione]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[classe php]]></category>
		<category><![CDATA[classi librerie]]></category>
		<category><![CDATA[csstidy]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[espressioni regolari]]></category>
		<category><![CDATA[ottimizzare]]></category>
		<category><![CDATA[regex]]></category>
		<category><![CDATA[richieste http]]></category>
		<category><![CDATA[servizi web]]></category>
		<category><![CDATA[sprite css]]></category>
		<category><![CDATA[yui compressor]]></category>
		<category><![CDATA[yui library]]></category>

		<guid isPermaLink="false">http://jblog.it/?p=640</guid>
		<description><![CDATA[Dopo gli articoli &#8220;ridurre le richieste HTTP (parte 1): come utilizzare la cache del browser&#8221; e &#8220;ridurre le richieste HTTP (parte 2): come unire e combinare immagini, script, css&#8221; vorrei parlarti delle tecniche per l&#8217;ottimizzazione dei componenti più comuni di una pagina web: immagini, script e css.

In questo articolo non verranno descritti dei metodi per [...]]]></description>
			<content:encoded><![CDATA[<p>Dopo gli articoli &#8220;<a href="http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html">ridurre le richieste HTTP (parte 1): come utilizzare la cache del browser</a>&#8221; e &#8220;<a href="http://jblog.it/2009/05/15/ridurre-richieste-http-parte-2-come-combinare-immagini-script-css-sprite-image-maps_405.html">ridurre le richieste HTTP (parte 2): come unire e combinare immagini, script, css</a>&#8221; vorrei parlarti delle tecniche per l&#8217;ottimizzazione dei componenti più comuni di una pagina web: immagini, script e css.</p>
<p><img class="aligncenter size-full wp-image-657" title="forty-nine: compressed work week" src="http://jblog.it/wp-content/uploads/2009/10/ottimizzare.jpg" alt="forty-nine: compressed work week" width="500" height="333" /></p>
<p><span class="highlight_yellow"><strong>In questo articolo</strong> non verranno descritti dei metodi per la riduzione delle richieste HTTP ma parlerò delle modifiche e degli strumenti che ti permetteranno di ottimizzare i componenti della pagina per velocizzarne le relative richieste HTTP.</span><br />
<span id="more-640"></span><br />
<!--adv300--></p>
<h2>Ottimizzare le immagini</h2>
<p>Anche se l&#8217;ottimizzazione non riduce le richieste http, è comunque importante per <strong>abbassare i tempi di caricamento</strong> delle pagine.</p>
<p>Ottimizzare un&#8217;immagine non è immediato; spesso sono necessarie molte prove e test per individuare il <strong>giusto bilanciamento</strong> fra qualità e dimensione del file.</p>
<p>Generalmente la compressione di un immagine è un&#8217;operazione da eseguire <strong>manualmente </strong>prima di caricare l&#8217;immagine nel proprio sito. Per fare ciò esistono numerosi <strong>script e tool gratuiti</strong>. Eccone alcuni.</p>
<div style="padding-left:20px;">
<h4><a href="http://www.imagemagick.org/" target="_blank">ImageMagick</a></h4>
<p><img class="alignright size-full wp-image-648" title="ImageMagick logo" src="http://jblog.it/wp-content/uploads/2009/06/logo.jpg" alt="ImageMagick logo" width="114" height="118" />ImageMagick è un set di librerie per creare, modificare e comporre immagini bitmap. Può leggere, convertire e scrivere immagini in vari formati (es. <strong>DPX, EXR, GIF, JPEG, JPEG-2000, PDF, PhotoCD, <a class="zem_slink" title="Portable Network Graphics" rel="wikipedia" href="http://en.wikipedia.org/wiki/Portable_Network_Graphics">PNG</a>, Postscript, SVG, e TIFF</strong>). ImageMagick, oltre alla rotazione e al ridimensionamento, permette di effettuare operazioni abbastanza complesse, applicare effetti speciali e tracciare forme.</p>
<p>Sul sito potrai trovare i libri consigliati (in lingua inglese) e tutto il necessario per iniziare a utilizzare queste librerie.</p>
<h4><a href="http://www.imagemagick.org/script/api.php" target="_blank">ImageMagick APIs</a></h4>
<p>ImageMagick include interfacce ed estensioni per utilizzare queste magnifiche librerie con i tuoi linguaggi di programmazione preferiti.</p>
<h4><a href="http://pmt.sourceforge.net/pngcrush/" target="_blank">PNGCrush</a></h4>
<p>PNGCrush è un tool per l&#8217;ottimizzazione di immagini PNG. Può essere eseguito dalla <strong>linea di comando di MSDOS, UNIX o LINUX</strong>. L&#8217;obiettivo principale è quello di ridurre la dimensione delle immagini PNG scegliendo vari livelli di compressione e filtri. Può essere anche utilizzato per purificare le immagini da tutte quelle informazioni aggiuntive lasciate dai vari software, o aggiungere altri tipi di blocchi.</p>
<h4><a href="http://jpegclub.org/jpegtran/" target="_blank">JPEGtran</a></h4>
<p>JPEGtran è una libreria per la trasformazioni di immagini JPEG con l&#8217;obiettivo di minimizzare la perdita informazioni e avere la maggior qualità possibile. Questa libreria comprende anche una funzione per determinare la miglior compressione per una certa immagine, in modo da evitare che si facciano numerosi test e verifiche.</p>
<p>Una <strong>guida </strong>sulle funzioni di questa libreria la puoi trovare <a href="http://www.gsp.com/cgi-bin/man.cgi?section=1&amp;topic=jpegtran" target="_blank">qui</a>.</p>
<h4><a href="http://tools.dynamicdrive.com/imageoptimizer/" target="_blank">Online Image Optimizer (GIF, JPG, and PNG)</a></h4>
<p><img class="alignright size-full wp-image-649" title="DynamicDrive Logo" src="http://jblog.it/wp-content/uploads/2009/06/logo.gif" alt="DynamicDrive Logo" width="200" height="30" />DynamicDrive ha sviluppato un ottimo tool per la compressione di immagini nei classici formati <strong>GIF, JPG e PNG</strong>. Questo è lo script originale sul quale sono nati numerosi servizi online per la compressione. Peccato che il limite sia di 300kb.</p>
<h4><a href="http://www.imageoptimizer.net/Pages/Home.aspx" target="_blank">Free Image Optimizer</a></h4>
<p><img class="alignright size-full wp-image-650" title="ImageOptimizer" src="http://jblog.it/wp-content/uploads/2009/06/banner.jpg" alt="ImageOptimizer" width="200" height="31" />Questo servizio web è un po&#8217; più evoluto rispetto a quello di <strong>DynamicDrive</strong> poiché non ti permette solo di compressare l&#8217;immagine ma anche di scegliere la dimensione di destinazione. Nel caso ti piacesse potrai scaricarne gratuitamente una versione trial.</p>
<h4><a href="http://luci.criosweb.ro/riot/" target="_blank">RIOT (Radical Image Optimization Tool)</a></h4>
<p><img class="alignright size-full wp-image-651" title="Radical Image Optimizer Tool" src="http://jblog.it/wp-content/uploads/2009/06/riot.jpg" alt="Radical Image Optimizer Tool" width="160" height="130" />RIOT è un <strong>software gratuito</strong> che ti aiuta a scegliere la miglior compressione osservandone i risultati in <strong>tempo reale</strong> grazie a un&#8217;interfaccia &#8220;dual view&#8221;. Grazie a questo software sarà facilissimo controllare la compressione, il numero di colori, le impostazioni, il formato delle immagini e molto altro. Compatibile con Windows 2000, XP e VISTA.</p>
<p>Sono disponibili anche le <strong>estensioni DLL </strong>per i più comuni linguaggi di programmazione (C, C++, Perl, PHP, Java, Phyton, ecc.).</p>
<h4><a href="http://www.softplatz.net/freeware/batch-image-compression/" target="_blank">Batch Image Compression Freeware</a></h4>
<p>Questa è un&#8217;enorme <strong>lista di software</strong> per la compressione e l&#8217;elaborazione di gruppi di immagini. Spazia dalla semplice conversione alla correzione di colore e occhi rossi. Assolutamente da vedere.</p>
</div>
<h2>Compressione di file CSS e Javascript</h2>
<p>Questa pratica (in inglese chiamata &#8220;minification&#8221;) consiste nel rimuovere dal codice tutti i caratteri non necessari in modo da ridurre la dimensione del file. Tecnicamente avviene quanto segue:</p>
<ul>
<li>vengono ristretti i nomi di variabili</li>
<li>caratteri di spaziatura come tab, a capo e spazio vengono eliminati (dove possibile)</li>
<li>vengono cancellati tutti i commenti</li>
</ul>
<p><strong>ATTENZIONE.</strong> Dopo la compressione il funzionamento degli script e i nomi delle funzioni rimangono invariati, quindi non è necessario modificare i file di template. In altre parole, i nomi delle variabili che vengono modificati sono i parametri locali delle funzioni, che non influenzano la modalità di chiamata delle funzioni.</p>
<h2>Offuscare il codice Javascript</h2>
<p><img class="alignright size-full wp-image-662" title="Offuscare javascript" src="http://jblog.it/wp-content/uploads/2009/06/2245309248_dc22bd13591.jpg" alt="Offuscare javascript" width="270" height="165" />Offuscare il codice (in inglese &#8220;obfuscate&#8221;, &#8220;obfuscation&#8221;) significa comprimerlo e trasformarlo in modo che risulti illeggibile (per i programmatori) per evitare che venga effettuato il cosiddetto reverse engineering, il procedimento attraverso cui è possibile leggere, capire ed utilizzare il codice di uno script.</p>
<p><strong>PRO:</strong> si raggiunge un ottimo livello di compressione, riducendo notevolmente la dimensione dello script.</p>
<p><strong>CONTRO:</strong> è un procedimento molto complesso attraverso cui si rischia di generare bug e malfunzionamenti; pertanto si consiglia di limitarsi esclusivamente a comprimere il codice anziché offuscarlo.</p>
<h2>Servizi web, librerie, software</h2>
<p>Ecco un po&#8217; di strumenti e servizi web per la compressione e l&#8217;offuscamento di file Javascript e CSS. Inizialmente trovi quelli riguardanti Javascript; in basso potrai vedere tutti quelli per la compressione di CSS.</p>
<h4><a href="http://yuilibrary.com/projects/yuicompressor/wiki" target="_blank">YUI Compressor</a></h4>
<p><img class="alignright size-full wp-image-652" title="YUI Library - Compressor" src="http://jblog.it/wp-content/uploads/2009/06/yuilibrary-masthead.png" alt="YUI Library - Compressor" width="180" height="46" />YUI Compressor è la più famosa libreria (open source) per la <strong>compressione di file CSS e Javascript</strong>. La compressione Javascript elimina commenti, caratteri di spaziatura e accorcia i nomi delle variabili. La compressione CSS utilizza un compressore basato su espressioni regolari.</p>
<h4><a href="http://www.crockford.com/javascript/jsmin.html" target="_blank">JSMin</a></h4>
<p>JSMin è un filtro che rimuove commenti e caratteri di spaziatura dai file <strong>Javascript</strong>. Generalmente la dimensione del file viene dimezzata. Questa libreria incoraggia i programmatori a esprimersi liberamente evitando che si preoccupino di risparmiare spazio. In fondo alla pagina puoi trovare i link per scaricare l&#8217;<strong>eseguibile MS-DOS.exe</strong> oppure i codici sorgenti in <strong>C, C#, Java, JavaScript, Perl, PHP, Python, OCAML, Ruby</strong>.</p>
<h4><a href="http://dojotoolkit.org/docs/shrinksafe" target="_blank">DojoToolkit ShrinkSafe</a></h4>
<p><img class="alignright size-full wp-image-653" title="Dojo Toolkit" src="http://jblog.it/wp-content/uploads/2009/06/images.jpg" alt="Dojo Toolkit" width="122" height="80" />Dojo, il famoso <strong>toolkit javascript</strong>, utilizza uno strumento per ridurre la dimensione, e quindi il tempo di caricamento, dei file <strong>Javascript</strong>. La particolarità sta nel fatto che invece di ricorrere alle solite espressioni regolari, Dojo Compressor è basato su <strong>Rhino</strong>, un javascript engine del progetto Mozilla. Quindi, poiché legge il flusso effettivo del codice javascript, può avere una visione migliore del contesto in cui una variabile viene letta e/o scritta, rispetto alle espressioni regolari.</p>
<h4><a href="http://dean.edwards.name/packer/" target="_blank">Packer</a></h4>
<p>Semplice servizio web per la <strong>compressione e l&#8217;offuscamento di codice Javascript</strong>. La libreria è disponibile anche per PHP e .NET. <strong>Download:</strong> <a href="http://dean.edwards.name/download/#packer" target="_blank">http://dean.edwards.name/download/#packer</a>.</p>
<h4><a href="http://web.2point1.com/2008/06/14/javascript-obfuscator-and-minifier/" target="_blank">JavaScript Obfuscator and Minifier</a></h4>
<p><strong>Librerie PHP</strong> per l&#8217;esecuzione da riga di comando. Richiedono la versione 5.2 (o superiore) di PHP CLI binary. Windows non è supportato e, a detta dello sviluppatore, non lo sarà mai.</p>
<p><strong>jsobf</strong>: compressa e offusca codice <strong>Javascript</strong>.</p>
<p><strong>jsfmt</strong>: effettua il <strong>processo inverso</strong> su un codice che ha subito compressione e offuscamento.</p>
<p><strong>Download</strong>: <a href="http://web.2point1.com/2008/09/07/jsfmt-and-jsobf-available-for-download/" target="_blank">http://web.2point1.com/2008/09/07/jsfmt-and-jsobf-available-for-download/</a>.</p>
<p><strong>Demo</strong>: <a href="http://timwhitlock.info/plug/examples/JavaScript/j_obfuscate.php" target="_blank">http://timwhitlock.info/plug/examples/JavaScript/j_obfuscate.php</a>.</p>
<h4><a href="http://farhadi.ir/works/smartoptimizer" target="_blank">SmartOptimizer</a></h4>
<p>SmartOptimizer (precedentemente chiamata JSmart) è una <strong>libreria PHP</strong> che si occupa di comprimere, offuscare, memorizzare in cache, fondere più file o stampare gli script direttamente nella pagina.</p>
<h4><a href="http://sourceforge.net/projects/packtag" target="_blank">pack:tag</a></h4>
<p><strong>Libreria JSP</strong> che compressa e combina risorse (come <strong>Javascript e CSS</strong>) e li memorizza nella cache del browser o in un file generato dinamicamente. Questo script si può inserire facilmente all&#8217;interno delle pagine e lavora in maniera trasparente sia all&#8217;utente sia allo sviluppatore.</p>
<h4><a href="http://tools.2vi.nl/" target="_blank">ObfuscateJS</a></h4>
<p><strong>Progetto Java</strong><strong> </strong>per la compressione e l&#8217;offuscamento di codice javascript. Si occupa di rimuovere caratteri di spaziatura e commenti, e di accorciare i nomi delle variabili locali.</p>
<h4><a href="http://jscompress.com/" target="_blank">JsCompress</a></h4>
<p>Servizio web per la compressione di <strong>codice javascript</strong>. Si può scegliere di eseguire la compressione con JsMin o con Packer. Molto interessante.</p>
<h4><a href="http://www.digitaloverload.co.uk/jsmin/" target="_blank">Javascript Minifier</a></h4>
<p>Servizio web (basato su JsMin) per la <strong>compressione di codice javascript</strong>. Puoi decidere se effettuare direttamente il download oppure visualizzare il risultato in una textarea.</p>
<h4><a href="http://www.javascriptobfuscator.com/" target="_blank">Free Javascript Obfuscator</a></h4>
<p>Servizio web che si occupa di <strong>comprimere e offuscare codice javascript</strong>. Offrendo diverse opzioni ti lascia libero di decidere completamente l&#8217;aspetto finale del codice.</p>
<h4><a href="http://www.daftlogic.com/projects-online-javascript-obfuscator.htm" target="_blank">Online Javascript Obfuscator</a></h4>
<p>Servizio web per la compressione e l&#8217;offuscamento di codice javascript.</p>
<h4><img class="alignright size-full wp-image-656" title="File CSS" src="http://jblog.it/wp-content/uploads/2009/06/page.png" alt="File CSS" width="128" height="128" /> <a href="http://www.ibloomstudios.com/articles/php_css_compressor" target="_blank">PHP CSS Compressor</a></h4>
<p>In questo articolo vengono fornite alcune <strong>righe di codice PHP</strong> da inserire direttamente nei <strong>file CSS</strong>. Questo codice provvede automaticamente alla compressione del contenuto del file CSS. In fondo all&#8217;articolo vengono descritte le modifiche da apportare al file .htaccess in modo che il file .css venga elaborato come file .php.</p>
<h4><a href="http://shygypsy.com/cssCompress/" target="_blank">CSS Compressor</a></h4>
<p>Servizio web per la <strong>compressione di codice CSS</strong>. L&#8217;applicazione è un&#8217;applet Java.</p>
<h4><a href="http://dotnetperls.com/Content/Minify-CSS.aspx" target="_blank">CSS Tidy</a></h4>
<p>Software, eseguibile da riga di comando, per la <strong>compressione di file CSS</strong>. La pagina del progetto è completa di tutta la documentazione necessaria per iniziare a utilizzarlo.</p>
<h2>Conclusione</h2>
<p><img class="alignright size-full wp-image-658" title="Analizza il tuo sito web" src="http://jblog.it/wp-content/uploads/2009/06/2349098787_2cd660c18c.jpg" alt="Analizza il tuo sito web" width="250" height="188" /><span class="highlight_green">Imparare a utilizzarli tutti è impossibile. Quindi, prima perder tempo tra download e righe di codice ti consiglio di <strong>analizzare il tuo sito</strong> per individuare i componenti che ne influenzano maggiormente le prestazioni.</span></p>
<p>Ad esempio, se il tuo sito è una <strong>galleria di immagini</strong> gestita con un paio di file javascript la cosa migliore da fare è scegliere il miglior tool per ottimizzare le foto, considerando anche il loro formato. Se, invece, hai un <strong>sito dinamico</strong> che fa un largo uso di javascript e tecniche Ajax, comprimere (e offuscare) il codice dei tuoi file javascript sarà fondamentale per migliorare il caricamento e la reattività del tuo sito web.</p>
<h4>Crediti</h4>
<ul>
<li><a title="Yahoo! Developer Network" href="http://developer.yahoo.com/" target="_blank">Yahoo! Developer Network</a> &#8211; <a title="Best Practices for Speeding Up Your Web Site" href="http://developer.yahoo.com/performance/rules.html" target="_blank">Best Practices for Speeding Up Your Web Site</a></li>
<li><strong>Foto1</strong>: forty-nine: <a title="forty-nine: compressed work week" href="http://www.flickr.com/photos/deadsquid/2614952166/" target="_blank">compressed work week</a> di <a href="http://www.flickr.com/photos/deadsquid/" target="_blank">dead_squid</a></li>
<li><strong>Foto2</strong>: <a title="fog over Istanbul skyscrapers" href="http://www.flickr.com/photos/whatcouldgowrong/2245309248/" target="_blank">fog over Istanbul skyscrapers</a> di <a href="http://www.flickr.com/photos/whatcouldgowrong/" target="_blank">WhatCouldPossiblyGoWrong?</a></li>
<li><strong>Foto3</strong>: <a title="MAGNIFYING GLASS" href="http://www.flickr.com/photos/andercismo/2349098787/" target="_blank">MAGNIFYING GLASS</a> di <a rel="dc:creator cc:attributionURL" href="http://www.flickr.com/photos/andercismo/" target="_blank">andercismo</a></li>
</ul>
<img src="http://jblog.it/?ak_action=api_record_view&id=640&type=feed" alt=" 20 servizi web e librerie per ottimizzare i componenti della pagina: immagini, javascript, css"  title="20 servizi web e librerie per ottimizzare i componenti della pagina: immagini, javascript, css" />]]></content:encoded>
			<wfw:commentRss>http://jblog.it/2009/06/10/ottimizzare-componenti-pagina-velocizzare-caricamento-immagini-css-script_640.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ridurre le richieste HTTP con Mime HTML e data:URL</title>
		<link>http://jblog.it/2009/06/01/ridurre-richieste-http-mime-html-data-url-mhtml_537.html</link>
		<comments>http://jblog.it/2009/06/01/ridurre-richieste-http-mime-html-data-url-mhtml_537.html#comments</comments>
		<pubDate>Mon, 01 Jun 2009 03:41:32 +0000</pubDate>
		<dc:creator>Giacomo</dc:creator>
				<category><![CDATA[Css]]></category>
		<category><![CDATA[Ottimizzazione]]></category>
		<category><![CDATA[Web design]]></category>
		<category><![CDATA[base64]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[classe php]]></category>
		<category><![CDATA[classi librerie]]></category>
		<category><![CDATA[data:URL]]></category>
		<category><![CDATA[mhtml]]></category>
		<category><![CDATA[mime]]></category>
		<category><![CDATA[multipart]]></category>
		<category><![CDATA[ottimizzare]]></category>
		<category><![CDATA[richieste http]]></category>
		<category><![CDATA[sprite css]]></category>

		<guid isPermaLink="false">http://jblog.it/?p=537</guid>
		<description><![CDATA[
Il Mime HTML e lo schema data:URL sono due importanti ingredienti nella ricetta che ti permetterà di ridurre le richieste HTTP.

Una pagina Mime HTML è un tipo di pagina web in cui è possibile scriverci sia il codice html sia dei dati come immagini, oggetti flash, file audio
Lo schema data:URL è una tecnica grazie alla [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://jblog.it/2009/06/01/ridurre-richieste-http-mime-html-data-url-mhtml_537.html"><img class="alignright size-full wp-image-559" title="MHTML Shake" src="http://jblog.it/wp-content/uploads/2009/06/senza-nome-33.jpg" alt="MHTML Shake" width="230" height="371" /></a></p>
<p>Il Mime HTML e lo schema data:URL sono due importanti ingredienti nella ricetta che ti permetterà di ridurre le richieste HTTP.</p>
<ul>
<li>Una pagina <strong>Mime HTML</strong> è un tipo di pagina web in cui è possibile scriverci sia il codice html sia dei dati come immagini, oggetti flash, file audio</li>
<li>Lo schema <strong>data:URL</strong> è una tecnica grazie alla quale è possibile inserire i dati nella pagina web (che abbiamo già visto nell&#8217;articolo <a title="Link permanente al post Ridurre le richieste HTTP (parte 2): come unire e combinare immagini, script, css" rel="bookmark" href="http://jblog.it/2009/05/15/ridurre-richieste-http-parte-2-come-combinare-immagini-script-css-sprite-image-maps_405.html">Ridurre le richieste HTTP (parte 2): come unire e combinare immagini, script, css</a> e che riprenderò per evitarti di fare su e giù per il blog)</li>
</ul>
<p>Non utilizzeremo queste due tecniche separatamente ma ci serviranno per creare il <strong>mix esplosivo</strong> <img src='http://jblog.it/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' title="Ridurre le richieste HTTP con Mime HTML e data:URL" />  per caricare quanti più dati possibile in una sola richiesta http: quella della pagina web.</p>
<h2>Lo schema data:URL</h2>
<p><!--adv300--></p>
<p>Per capire bene il Mime HTML è necessario sapere come codificare i file in base64 e come utilizzarli all&#8217;interno della pagina per poi vedere l&#8217;intera struttura di un documento MHTML.</p>
<p>Il vantaggio fondamentale di questa tecnica consiste nel risparmio di tante richieste http quanti sono gli oggetti e le immagini codificati in base64 che inseriamo nella pagina.<span id="more-537"></span></p>
<p>Vediamo subito un <strong>esempio</strong>.</p>
<pre lang="html">&lt;IMG ALT="Foto" SRC="data:image/gif; base64,
	R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwhhx4dbgYKAAA7B72VFgl2Tf7452
	AAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFz
	ByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSp
	a/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJl
	ZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uis
	F81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PH" /&gt;</pre>
<p>Dopo la paura iniziale, in genere ci si domanda: <strong>cosa sono quei caratteri e come faccio a inserirli?</strong></p>
<p>Quell&#8217;ammasso di caratteri è la <strong>codifica in base64</strong> dell&#8217;immagine. In pratica, è il contenuto del file immagine codificato in base64.</p>
<p>Per<strong> codificare un&#8217;immagine in base64</strong> si utilizza una semplice <strong>funzione php</strong>: <em>base64_encode</em>.</p>
<p>L&#8217;ultima questione riguarda il tipo <strong>MIME</strong> che si può ottenere in due modi:</p>
<ul>
<li>utilizzando la funzione <strong>mime_content_type</strong>, dopo aver abilitato l&#8217;<strong>estensione php_mime_magic.dll</strong>.</li>
<li>leggendo le informazioni del file grazie le funzioni <a title="File Information" href="http://it2.php.net/manual/en/book.fileinfo.php"><strong>File Information</strong></a> di php. Era un&#8217;estensione PECL, ma ora non lo è più. Bisogna utilizzare la <strong>libreria esterna magic_open</strong></li>
</ul>
<p>Nel caso non si possano utilizzare queste funzioni si dovrà <strong>scrivere manualmente</strong>, il che presuppone che si conosca il tipo dell&#8217;oggetto o dell&#8217;immagine da inserire.</p>
<h4>Come inserire un&#8217;immagine in base64 (senza funzioni per il tipo MIME)</h4>
<pre lang="php">&lt;img src="data:image/jpeg;base64,&lt;?
echo base64_encode(file_get_contents("img.jpg")); ?&gt;" alt="Immagine" /&gt;</pre>
<h4>Come inserire un&#8217;immagine in base64 (con funzioni per il tipo MIME)</h4>
<pre lang="php">&lt;? $mime = mime_content_type("img.jpg"); ?&gt;
&lt;img src="data:&lt;? echo $mime; ?&gt;;base64,&lt;?
echo base64_encode(file_get_contents("img.jpg")); ?&gt;" alt="Immagine" /&gt;</pre>
<h4>Script, demo e download</h4>
<p>Per vedere lo script vai a <a href="http://test.jblog.it/img_base64/index.txt" target="_blank">http://test.jblog.it/img_base64/index.txt</a></p>
<p>Per vedere una demo vai a <a href="http://test.jblog.it/img_base64/" target="_blank">http://test.jblog.it/img_base64/</a></p>
<p>Per scaricare l&#8217;esempio vai a <a href="http://download.jblog.it/img_base64.zip" target="_blank">http://download.jblog.it/img_base64.zip</a></p>
<h2>Mime HTML</h2>
<p>Il termine &#8220;<em>Mime HTML</em>&#8221; sta per &#8220;<em>Multipurpose Internet Mail Extensions HyperText Markup Language</em>&#8220;.</p>
<p>Per avere un&#8217;idea di quella che può essere una pagina mhtml (di estensione .mht) pensiamo ad un&#8217;<strong>email con dei file allegati</strong> (che possono essere anche delle immagini presenti all&#8217;interno del testo). I file che vengono inviati tramite email, sottoforma di allegati, vengono codificati in <strong>base64 </strong>e successivamente inseriti nell&#8217;intestazione dell&#8217;email. Quando il nostro client riceve l&#8217;email, prima decodifica gli allegati per renderli fruibili ed eventualmente pronti per il download. Una pagina MHTML funziona grosso modo così.</p>
<p><strong>ATTENZIONE.</strong> Una pagina MHTML non deve necessariamente essere quella in cui viene scritto il codice html. Infatti può esserlo anche un file css che utilizza delle immagini (che vedremo successivamente).</p>
<h3>Struttura di una pagina MHTML</h3>
<p><img class="alignright size-full wp-image-545" title="Schema Pagina MHTML" src="http://jblog.it/wp-content/uploads/2009/05/mhtml_schema.png" alt="Schema Pagina MHTML" width="271" height="253" />Generalmente una pagina di questo tipo è composta da <strong>3 mattoni fondamentali</strong>:</p>
<ul>
<li>nell&#8217;<strong>intestazione </strong>si specifica che il file è di tipo &#8220;multipart/related&#8221;, il separatore dei dati codificati in base64 e il tipo di contenuto del file (es. &#8220;text/html&#8221;)</li>
<li>la seconda parte è quella relativa ai <strong>dati codificati in base 64</strong> separati dal separatore specificato nell&#8217;intestazione e definiti dai rispettivi campi &#8220;Content-Location&#8221;, &#8220;Content-Type&#8221; e &#8220;Content-Transfer-Encoding&#8221; (naturalmente, quest&#8217;ultimo viene impostato con &#8220;base64&#8243;). Possono trovarsi anche in fondo alla pagina, il che è meglio poiché si da priorità al caricamento del codice</li>
<li>nella terza parte viene scritto il <strong>corpo della pagina</strong> (o del messaggio, nel caso delle email) in html, css o altro, all&#8217;interno del quale verranno richiamati i dati specificati nella seconda parte del documento</li>
</ul>
<h3>Esempio di documento</h3>
<p>L&#8217;esempio seguente è una pagina web con allegate 2 immagini, e segue lo schema in figura.</p>
<p>Purtroppo <strong>Internet Explorer</strong> gestisce diversamente i dati allegati e ci costringe a scrivere due versioni di codice. Tuttavia, questa è una delle rare volte in cui preferisco IE poiché con il browser Microsoft i dati in base64 vengono scritti una sola volta e possono essere <strong>richiamati infinite volte </strong>all&#8217;interno del documento grazie alla stringa specificata in &#8220;Content-Location&#8221;. Con <strong>gli altri browser</strong> (Firefox, Opera, Safari, Chrome) è necessario scrivere i dati codificati per ogni utilizzo dell&#8217;oggetto o immagine, il che rende il tutto più pesante e ci costringe a pensare due volte prima di decidere di inviare un&#8217;oggetto all&#8217;interno del documento MIME Html.</p>
<pre lang="html">&lt;!--
MIME-Version: 1.0
Content-Type: multipart/related; boundary="|b|o|u|n|d|a|r|y|"

--|b|o|u|n|d|a|r|y|
Content-Location:2bmp24869
Content-Type:image/bmp
Content-Transfer-Encoding:base64

Qk0eCgAAAAAAADYEAAAoA[...caratteri...]QEBAQEBAQEBZA==
--|b|o|u|n|d|a|r|y|
Content-Location:1bmp21242
Content-Type:image/bmp
Content-Transfer-Encoding:base64

Qk12CwAAAAAAAD[...caratteri...]JCQkJCQkJ
--&gt;
&lt;!--
--|b|o|u|n|d|a|r|y|
Content-Location:5bmp92853
Content-Type:image/bmp
Content-Transfer-Encoding:base64

<span class="attribute-value">DCwmoA2NiOAKioQ</span>[...caratteri...]<span class="attribute-value">QDz87gA0dGCALq6X</span>
--&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"  dir="ltr" lang="en-US"&gt;
&lt;head&gt;
  &lt;title&gt;Titolo pagina&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;

	&lt;object data="data:image/bmp;base64,Qk0eCgAAAAAAADYEAAAoA[...caratteri...]QEBAQEBAQEBZA=="&gt;
		&lt;img src="mhtml:http://localhost/jblog_script/mhtml_dataurl/index2.php!2bmp24869" alt="img3" /&gt;
	&lt;/object&gt;

	&lt;div style=" width:200px; height:200px; background-image:url(data:image/bmp;base64,Qk12CwAAAAAAAD[...caratteri...]JCQkJCQkJ); *background-image:url(mhtml:http://localhost/jblog_script/mhtml_dataurl/index2.php!1bmp21242);"&gt;&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Il fatto che queste immagini abbiano questo &#8220;strano&#8221; formato non ci deve assolutamente far preoccupare. Gli utilizzi sono quelli di sempre: all&#8217;interno del tag &lt;img&gt;, come sfondo di un elemento grazie alle regole css, ecc.</p>
<p><strong>Compatibilità con IE.</strong> Per gestire la compatibilità con il browser Internet Explorer è necessario inserire l&#8217;immagine compatibile con IE all&#8217;interno dei tag &lt;object&gt; in cui viene specificata l&#8217;immagine in un formato compatibile con i restanti browser. I risultati sono i seguenti:</p>
<ul>
<li>se si accede alla pagina con un <strong>browser diverso da IE</strong>, il tag object funzionerà correttamente mostrando l&#8217;immagine; il tag &lt;img&gt; al suo interno non verrà preso in considerazione dal browser</li>
<li>nel caso in cui si acceda con <strong>Internet Explorer</strong>, poiché il tag &lt;object&gt; non funzionerà verrà considerato il tag &lt;img&gt; in cui l&#8217;immagine specificata è in un formato compatibile con IE</li>
</ul>
<p><strong>Regole da rispettare.</strong> Per concludere vorrei evidenziare alcune importanti caratteristiche riguardo il formato di un documento MHTML:</p>
<ul>
<li>&#8220;Mime Version&#8221; e &#8220;Content-Type&#8221; devono trovarsi obbligatoriamente in testa alla pagina, prima del &lt;!Doctype&#8230;&gt;</li>
<li>Il primo separatore può essere separato a piacere dall&#8217;intestazione del documento</li>
<li>Il separatore (boundary) deve trovarsi esattamente fra i dati in base64 dell&#8217;oggetto precedente e le intestazioni dell&#8217;oggetto successivo, senza ulteriori &#8220;a capo&#8221;, &#8220;spazi&#8221;, &#8220;tab&#8221;, e altri caratteri</li>
<li>I vari oggetti possono essere separati solo da &#8220;fine&#8221; (&#8211;&gt;) e &#8220;inizio&#8221; (&lt;!&#8211;) commenti, stando attenti a non inserire altri caratteri tra &lt;!&#8211; e il separatore; invece, fra il contenuto in base64 e &#8211;&gt; possono esserci caratteri di escape (a capo, tab, ecc.)</li>
<li>Prima del separatore è necessario inserire due trattini &#8220;&#8211;&#8221;</li>
<li>Riguardo IE, l&#8217;indirizzo da scrivere dopo <strong>mhtml:</strong> deve essere identico all&#8217;indirizzo visibile nella barra degli indirizzi. Questo indirizzo si ottiene dalla variabile riservata <strong>$_SERVER['REQUEST_URI']</strong></li>
</ul>
<h2>Utilizzare concretamente Mime HTML e data:URL</h2>
<p>Ecco come immagino la generazione di un documento Mime HTML con lo schema data:URL.</p>
<p><img class="aligncenter size-full wp-image-553" title="Schema MHTML e data:URL, processo" src="http://jblog.it/wp-content/uploads/2009/06/mhtml_dataurl.png" alt="Schema MHTML e data:URL, processo" width="507" height="268" /><strong>Prima fase.</strong> Gli oggetti e le immagini vengono codificati in base64 e sistemati all&#8217;interno del documento.</p>
<p><strong>Seconda fase.</strong> Il browser legge il codice html e decodifica i dati allegati portandoli al loro formato primitivo: le immagini ritornano immagini, gli oggetti flash ritornano animazioni, ecc.</p>
<h3>La classe MimeHtmlHandler</h3>
<p>Per automatizzare il tutto ho sviluppato una piccola classe PHP che con un paio di righe ti permetterà di inserire all&#8217;interno del documento MHtml un&#8217;immagine precedentemente allegata.</p>
<p><strong>N.B.</strong> la proprietà <strong>*background-image </strong>serve per rimpiazzare la prima background-image nel caso questa non funzionasse. In particolare, la proprietà *background-image viene utilizzata per IE mentre background-image funziona con i restanti browser.</p>
<p>Il codice dell&#8217;esempio precedente è stato ottenuto da questo script PHP:</p>
<pre lang="php">&lt;?
// ( 1 ) Crea l'oggetto
$mhh = new MimeHtmlHandler("http://test.jblog.it","|b|o|u|n|d|a|r|y|","MIME Version 1.0");

// ( 2 ) Header "Content-Type" e "MIME Version"
$mph-&gt;printHeader();

?&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"  dir="ltr" lang="en-US"&gt;
&lt;head&gt;
  &lt;title&gt;mhtml test page&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;div id="test1"&gt;test #1&lt;/div&gt;
  &lt;div id="test2"&gt;test #2&lt;/div&gt;

  &lt;object data="&lt;? $mhh-&gt;inc("2.bmp","image/bmp"); ?&gt;"&gt;
	  &lt;img src="&lt;? $mhh-&gt;incIE("2.bmp"); ?&gt;" alt="img3" /&gt;
  &lt;/object&gt;

 &lt;div style=" width:200px; height:200px; background-image:url(&lt;? $mhh-&gt;inc("1.bmp","image/bmp"); ?&gt;); *background-image:url(&lt;? $mhh-&gt;incIE("1.bmp"); ?&gt;);"&gt;&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
&lt;?
// ( 3 ) Crea la lista dei dati (per IE)
$mhh-&gt;incAll();
?&gt;</pre>
<h4>Caratteristiche principali della classe MimeHtmlHandler</h4>
<p>La classe ha due <strong>array privati</strong>: il primo è quello in cui vengono conservati gli oggetti che vengono inseriti nella pagina in modo da evitare di codificarli e impostarli nuovamente per un successivo inserimento; il secondo è quello relativo ai nomi in codice specificati in &#8220;Content-Location&#8221; quando si stampa la lista dei dati codificati che verrà utilizzata solo da Internet Explorer.</p>
<p>Le <strong>funzioni da utilizzare</strong> sono solo due: inc e incIE. Queste due funzioni permettono di inserire oggetti in formati compatibili con tutti i browser e con IE. Inoltre, in base al tipo e al numero di argomenti passati è possibile creare da zero un oggetto o richiamarne uno già inserito.</p>
<p>Quando si vuole stampare un&#8217;oggetto già inserito precedentemente il nome del file verrà cercato nell&#8217;array degli oggetti. La <strong>ricerca </strong>viene effettuata a partire dall&#8217;<strong>ultimo elemento</strong> in quanto sono molto più probabili gli inserimenti consecutivi di immagini rispetto a quelli richiesti in punti molto diversi e lontani di una pagina.</p>
<h4>Le 3 istruzioni fondamentali</h4>
<ol>
<li>Crea l&#8217;oggetto della classe specificando l&#8217;url di base delle immagini, il separatore (boundary) e la versione MIME</li>
<li>Stampa l&#8217;intestazione &#8220;Content-Type&#8221; e &#8220;MIME Version&#8221;</li>
<li>In fondo alla pagina viene stampata la lista dei dati in base64 che servono a Internet Explorer, mentre per gli altri browser i dati codificati vengono specificati all&#8217;interno del tag in cui si utilizzano</li>
</ol>
<h4>Come inserire un&#8217;immagine</h4>
<p>Sono state create due funzioni distinte per l&#8217;inserimento di un&#8217;immagine compatibile con IE o con gli altri browser (rispettivamente incIE e inc). Analizziamo i casi più comuni relativi all&#8217;utilizzo di queste funzioni.</p>
<ul>
<li><strong>Inserire un&#8217;immagine in modo che sia compatibile con tutti i browser. </strong>Richiamare la funzione inc() all&#8217;interno dell&#8217;attributo &#8220;data&#8221; del tag &lt;object&gt;, passando come parametri il percorso del file e il tipo mime. All&#8217;interno dei tag &lt;object&gt; e &lt;/object&gt; inserire il tag &lt;img&gt; richiamando la funzione incIE() all&#8217;interno dell&#8217;attributo &#8220;src&#8221;. Alla funzione incIE basterà passare solo il nome del file grazie al quale verranno recuperati gli altri dati relativi all&#8217;oggetto da stampare.</li>
<li><strong>Inserire un&#8217;immagine esistente.</strong> Alle funzioni inc() e incIE() basterà passare il nome del file.</li>
</ul>
<h4>Demo e download</h4>
<p>Per vedere una demo vai su <a href="http://test.jblog.it/mhtml1/index.php" target="_blank">http://test.jblog.it/mhtml1/</a></p>
<p>Per scaricare la classe MimeHtmlHandler e l’esempio vai su <a href="http://download.jblog.it/mhtml1.zip" target="_blank">http://download.jblog.it/mhtml1.zip</a></p>
<h2>Esempio2. CSS e data:URL</h2>
<p>Per utilizzare la classe MimeHtmlHandler all&#8217;interno di un file CSS, la prima operazione da fare è impostare il server Apache in modo che processi i file CSS come file PHP. Per fare ciò basterà aggiungere queste righe:</p>
<pre>&lt;FilesMatch "myfile.css$"&gt;
	AddHandler application/x-httpd-php .css
&lt;/FilesMatch&gt;</pre>
<p>Infine componiamo il file css:</p>
<ul>
<li>processandolo come file php si perde la natura del file css che ripristiniamo inviando l&#8217;header &#8220;Content-Type:text/css&#8221;</li>
<li>includiamo la classe MimeHtmlHandler, e richiamiamo le prime due funzioni fondamentali (costruttore e printHeader() )</li>
<li>componiamo il corpo del file css utilizzando, dove occorrono, le funzioni inc() e incIE()</li>
<li>infine, richiamiamo l&#8217;ultima funzione fondamentale incAll() per stampare la lista dei file che servirà ad Internet Explorer</li>
</ul>
<pre lang="php">&lt;? header("Content-Type: text/css"); ?&gt;
/*&lt;?
include("MimeHtmlHandler.php");

// ( 1 ) Crea l'oggetto
$mhh = new MimeHtmlHandler("http://localhost","|b|o|u|n|d|a|r|y|","");

// ( 2 ) Header "Content-Type" e "MIME Version"
$mhh-&gt;printHeader();
?&gt;*/

#test1 {
  background-image: url("&lt;? $mhh-&gt;inc("2.bmp","image/bmp"); ?&gt;"); /* normal */
  *background-image: url(&lt;? $mhh-&gt;incIE("2.bmp"); ?&gt;); /* IE &lt; 8 */
}

#test2 {
  background-image: url("&lt;? $mhh-&gt;inc("1.bmp","image/bmp"); ?&gt;"); /* normal */
  *background-image: url(&lt;? $mhh-&gt;incIE("1.bmp"); ?&gt;); /* IE &lt; 8 */
}

div {
  width: 100px;
  height: 100px;
  font: bold 24px Arial;
}
/*&lt;?
// ( 3 ) Crea la lista dei dati (per IE)
$mhh-&gt;incAll();

?&gt;*/</pre>
<h4>Demo e download</h4>
<p>Per vedere una demo vai su <a href="http://test.jblog.it/mhtml2/index.php" target="_blank">http://test.jblog.it/mhtml2/</a></p>
<p>Per scaricare la classe MimeHtmlHandler e l’esempio vai su <a href="http://download.jblog.it/mhtml2.zip" target="_blank">http://download.jblog.it/mhtml2.zip</a></p>
<h2>Considerazioni finali</h2>
<p>Nei precedenti esempi abbiamo visto solo come utilizzare queste tecniche per allegare le immagini, anche perché è questa la situazione più frequente. Tuttavia, nello stesso modo potresti allegare facilmente <strong>oggetti flash e applet Java</strong>: nello stesso modo!</p>
<p><strong>Compatibilità IE.</strong> Ho testato queste tecniche con Internet Explorer, dalla versione 5.5 alla 8 e non ho riscontrato grossi problemi. Una piccola anomalia si verifica quando si aggiorna la pagina più volte e le immagini non vengono caricate. Sinceramente non so da cosa può dipendere.</p>
<p>Queste tecniche, in confronto ai CSS Sprite sembrano<strong> &#8220;roba da smanettoni&#8221;</strong> a causa dell&#8217;ammasso di numeri e lettere che genera la codifica in base64 e dell&#8217;utilizzo (leggero) di php. Non farti ingannare&#8230; In fondo cosa c&#8217;è di così difficile?!? Dovrai solo pensare alcuni minuti alle immagini da allegare ai documenti (html, css, ecc.) e analizzare un po&#8217; le velocità di caricamento per capire fino a che punto potranno avvantagiarti. Io dico di provarci! <img src='http://jblog.it/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' title="Ridurre le richieste HTTP con Mime HTML e data:URL" /> </p>
<p><span class="highlight_green">Non escludo che nella classe MimeHtmlHandler ci possano essere dei <strong>bug</strong>. Per qualsiasi problema, chiarimento e curiosità sarei felice se mi contattattassi. Dimmi com&#8217;è andata e se queste tecniche ti sono state utili: non vedo l&#8217;ora di sapere gli esiti dei tuoi esperimenti!</span></p>
<h2>Crediti</h2>
<p><a href="http://www.phpied.com/" target="_blank">Phpied.com</a> &#8211; <a href="http://www.phpied.com/data-urls-what-are-they-and-how-to-use/" target="_blank">data:urls &#8211; what are they and how to use them</a></p>
<p><a href="http://www.phpied.com/" target="_blank">Phpied.com</a> &#8211; <a href="http://www.phpied.com/mhtml-when-you-need-data-uris-in-ie7-and-under/" target="_blank">MHTML &#8211; when you need data: URIs in IE7 and under</a></p>
<p><strong>Foto1.</strong> <a href="http://www.flickr.com/photos/benbeiske/3028805547/" target="_blank">Vientiane 04 &#8211; Pink Dragonfruit shake</a> di <a href="http://www.flickr.com/photos/benbeiske/">Ben Beiske</a></p>
<img src="http://jblog.it/?ak_action=api_record_view&id=537&type=feed" alt=" Ridurre le richieste HTTP con Mime HTML e data:URL"  title="Ridurre le richieste HTTP con Mime HTML e data:URL" />]]></content:encoded>
			<wfw:commentRss>http://jblog.it/2009/06/01/ridurre-richieste-http-mime-html-data-url-mhtml_537.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Ridurre le richieste HTTP (parte 2): come unire e combinare immagini, script, css</title>
		<link>http://jblog.it/2009/05/15/ridurre-richieste-http-parte-2-come-combinare-immagini-script-css-sprite-image-maps_405.html</link>
		<comments>http://jblog.it/2009/05/15/ridurre-richieste-http-parte-2-come-combinare-immagini-script-css-sprite-image-maps_405.html#comments</comments>
		<pubDate>Fri, 15 May 2009 15:04:06 +0000</pubDate>
		<dc:creator>Giacomo</dc:creator>
				<category><![CDATA[Css]]></category>
		<category><![CDATA[Grafica]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Ottimizzazione]]></category>
		<category><![CDATA[Web design]]></category>
		<category><![CDATA[base64]]></category>
		<category><![CDATA[classe php]]></category>
		<category><![CDATA[data:URL]]></category>
		<category><![CDATA[ottimizzare]]></category>
		<category><![CDATA[richieste http]]></category>
		<category><![CDATA[sprite css]]></category>

		<guid isPermaLink="false">http://jblog.it/?p=405</guid>
		<description><![CDATA[Dopo il precedente articolo su come utilizzare la cache del browser passiamo ad azioni più concrete per ridurre le richieste http: minimizzare il numero di componenti di una pagina. Dico &#8220;concrete&#8221; perché, mentre i comportamenti e le tecniche relative alla cache possono avere effetti diversi a seconda del browser e delle sue impostazioni, diminuire i [...]]]></description>
			<content:encoded><![CDATA[<p><a title="Ridurre le richieste HTTP (parte 2): come unire e combinare immagini, script, css" href="http://jblog.it/2009/05/15/ridurre-richieste-http-parte-2-come-combinare-immagini-script-css-sprite-image-maps_405.html" target="_blank"><img class="alignright size-full wp-image-438" title="Ghepardo in corsa" src="http://jblog.it/wp-content/uploads/2009/05/2913134974_6d1839b33b.jpg" alt="2913134974 6d1839b33b Ridurre le richieste HTTP (parte 2): come unire e combinare immagini, script, css" width="300" height="154" /></a>Dopo il precedente articolo su <a title="Ridurre le richieste HTTP (parte 1): come utilizzare la cache del browser" rel="bookmark" href="http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html">come utilizzare la cache del browser</a> passiamo ad <strong>azioni più <em>concrete</em></strong><em> </em>per ridurre le richieste http: <strong>minimizzare il numero di componenti di una pagina</strong>. Dico &#8220;concrete&#8221; perché, mentre i comportamenti e le tecniche relative alla cache possono avere effetti diversi a seconda del browser e delle sue impostazioni, diminuire i componenti di una pagina è qualcosa che <strong>dipende esclusivamente dal webmaster</strong>, con risultati e prestazioni prevedibili.</p>
<h4>Gestire la cache è fatica sprecata?</h4>
<p><strong>Assolutamente no!</strong> Il fatto è che ogni utente che accede al sito la prima volta deve comunque attendere il caricamento completo della pagina e dei suoi componenti, che vengono subito memorizzati in cache. Il miglioramento di prestazioni si verifica a partire dalla seconda pagina che viene visitata in quanto i componenti vengono letti dalla cache, evitando di effettuare nuove (e inutili) richieste http.</p>
<h4>Vantaggi immediati</h4>
<p>Diminuire i componenti di una pagina consente di avere un notevole aumento delle prestazioni che <strong>migliora l&#8217;esperienza tutti gli utenti</strong>, vecchi e nuovi, dalla prima all&#8217;ultima pagina.</p>
<p><span class="highlight_yellow"><strong>In questo articolo</strong> vedremo alcune tecniche che <strong>riducono drasticamente</strong> il numero e il tempo di caricamento relativo a immagini, script e css. Queste tecniche non fanno altro che <strong>combinare questi componenti</strong> in modo da caricarne pochi ma più pesanti anziché molti ma leggeri. Parleremo di image maps, sprite css, dello schema data:URL, di generatori di sprite css, di come combinare automaticamente javascript e css, vedremo che a volte è meglio inserire il codice direttamente nella pagina html, e come è possibile evitare gli script duplicati.</span><span id="more-405"></span></p>
<h2>Pochi ma buoni</h2>
<p><!--adv300--></p>
<p><img class="alignright size-full wp-image-439" title="Olimpiadi Pechino - Ciclismo" src="http://jblog.it/wp-content/uploads/2009/05/cic02.jpg" alt="Olimpiadi Pechino - Ciclismo" width="270" height="180" />A primo impatto potrebbe sembrare un&#8217;assurdità affermare che &#8220;è meglio caricare un file da 300 kbyte anziché 10 file da 40kb&#8221;. Fortunatamente non lo è!</p>
<p>Infatti, se prendiamo 10 immagini e le copiamo all&#8217;interno di un solo file immagine, quest&#8217;ultimo file occuperà molto meno rispetto alla somma delle 10 immagini. <strong>Il motivo</strong> è che nei file vengono memorizzate tantissime informazioni oltre al contenuto che i software ci mostrano.</p>
<p><strong>Ad esempio</strong>, se apriamo una fotografia quello che vediamo è semplicemente un&#8217;immagine. Tuttavia, quel file contiene anche una serie di informazioni come: modello fotocamera, altezza, larghezza, risoluzione, ecc.</p>
<p>Caricare una sola immagine (ed un set di informazioni) è meglio che caricare dieci immagini (e dieci set di informazioni) perché:</p>
<ul>
<li>la dimensione del file più grosso è minore della somma di tanti file più piccoli</li>
<li>tante richieste http si riducono a una sola</li>
</ul>
<p>Mentre sulla riduzione delle richieste http possiamo essere d&#8217;accordo, credo che tu abbia qualche dubbio sul fatto che diminuisca la dimensione del file più grande. Bene, fai questo<strong> semplice esperimento</strong>:</p>
<ul>
<li>prendi un&#8217;immagine e fanne 10 copie</li>
<li>crea un&#8217;immagine grande abbastanza da contenere perfettamente 10 immagini uguali</li>
<li>confronta la dimensione dei 10 file immagine con quella del file immagine più grande</li>
</ul>
<h4>I componenti incriminati</h4>
<p>Generalmente si focalizza l&#8217;attenzione su immagini, javascript e css perché sono presenti in tutte le pagine e, se mal gestiti, non solo provocano un eccessivo numero di richieste http ma rallentano il normale caricamento delle pagine.</p>
<h2>Combinare le immagini: &#8220;image maps&#8221;</h2>
<p><img class="alignright size-full wp-image-440" title="Puzzle di gatti" src="http://jblog.it/wp-content/uploads/2009/05/312855876_abbdbcf21b.jpg" alt="Puzzle di gatti" width="270" height="162" />Se vogliamo inserire due immagini affiancate basta combinarle in un unico file immagine e inserire quest&#8217;ultimo all&#8217;interno della pagina.</p>
<p>I problemi nascono nel momento in cui, ad esempio, vogliamo applicare un diverso link a ciascuna immagine. Infatti, essendo un&#8217;unica immagine, non possiamo racchiuderla all&#8217;interno di un tag &lt;a&gt;, ma dobbiamo <strong>&#8220;mappare&#8221; le immagini</strong>.</p>
<p>Prima di illustrare i tre metodi è necessario descrivere gli <strong>strumenti a nostra disposizione</strong>.</p>
<h4>Il tag &lt;area&gt;</h4>
<p>Serve per creare le singole aree, cliccabili o meno, dell&#8217;immagine. Non richiede il tag di chiusura completo (&lt;/area&gt;).</p>
<p><strong>Formato</strong>. <code>&lt;area shape="..." coords="..." href="http://example.com/link1.html"&gt;</code></p>
<p><span class="highlight_green">Per creare<strong> documenti più accessibili</strong>, si può utilizzare il tag &lt;a&gt;&#8230;&lt;/a&gt; con gli stessi attributi di &lt;area&gt;. Infatti, grazie al tag &lt;a&gt; si può specificare un testo alternativo per l&#8217;area.</span></p>
<p><strong>Formato</strong>. <code>&lt;a </code><code>href="http://example.com/link1.html" </code><code>shape="..." coords="..." /&gt;Area1&lt;/a&gt;<br />
</code></p>
<p><strong>shape</strong>: (default, rect, circle, poly), cioè (default, rettangolo, cerchio, poligono). Specifica la forma di una regione.</p>
<p><strong>coords</strong>: coordinate. Specificano la posizione e la sagoma. Il numero e l&#8217;ordine dei valori dipendono dalla forma specificata da <em>shape</em>.</p>
<ul>
<li><em>rect</em>: left-x, top-y, right-x, bottom-y. I vertici opposti del rettangolo.</li>
<li><em>circle</em>: center-x, center-y, radius. Coordinate del centro e lunghezza del raggio.</li>
<li><em>poly</em>: x1, y1, x2, y2, &#8230;, xN, yN. Coordinate di tutti i vertici del poligono.</li>
</ul>
<p><strong>href</strong>: link associato alla regione.</p>
<p><strong>nohref</strong>: impostare con true per specificare che la regione non ha link associati, altrimenti non impostare.</p>
<h4>Il tag &lt;map&gt;</h4>
<p>Specifica una mappa da far richiamare da un oggetto. È richiesto il tag di chiusura &lt;/map&gt;.</p>
<p>All&#8217;interno dei tag &lt;map&gt;&#8230;&lt;/map&gt; si inseriscono tutte le aree relative alla mappa.</p>
<p><strong>name</strong>. Assegna un nome alla mappa.</p>
<h4>Associare una mappa a un elemento</h4>
<p>Utilizzare l&#8217;attributo <strong>usemap</strong> fra gli attributi dell&#8217;elemento, specificando un URI.</p>
<p>Ricorda che un URI può essere un indirizzo del tipo http://www.example&#8230; o un id del tipo #nome-mappa.</p>
<p><strong>Formato</strong>. <code>&lt;img src="foto.jpg" alt="La mia foto" usemap="mappafoto" /&gt;</code></p>
<h3>Image maps lato client</h3>
<p>La presenza di usemap <strong>implica che l&#8217;oggetto sia un immagine</strong>. Se non lo è, i browser potrebbero comunque implementare un&#8217;interazione con l&#8217;utente simile a quella per le immagini. Purtroppo <strong>non tutti i browser</strong> eseguono correttamente la mappatura di un immagine o di un oggetto.</p>
<p>Un blocco &lt;map&gt; può contenere sia elementi &lt;area&gt; sia elementi a livello di blocco come &lt;a&gt; per aumentare la compatibilità con i browser più datati.</p>
<h4>Alcune osservazioni</h4>
<ol>
<li>Se sono presenti contemporaneamente &lt;a&gt; ed &lt;area&gt;, i browser recenti ignorano il tag &lt;area&gt;</li>
<li>Se due o più regioni si sovrappongono, la prima regione avrà la precedenza sulle altre</li>
<li>L&#8217;elemento &lt;map&gt; non è compatibile con i browser HTML 2.0</li>
</ol>
<h4>Demo e download</h4>
<p>Per vedere una demo vai a <a href="http://test.jblog.it/imagemap_cs/" target="_blank">http://test.jblog.it/imagemap_cs/</a></p>
<p>In quest&#8217;altro esempio le aree sono rettangolari, circolari e poligonali. <a href="http://test.jblog.it/imagemap_cs2/" target="_blank">http://test.jblog.it/imagemap_cs2/</a></p>
<p>Per scaricare entrambi gli esempi vai a <a href="http://download.jblog.it/imagemap_cs_cs2.zip" target="_blank">http://download.jblog.it/imagemap_cs_cs2.zip</a></p>
<h4>Esempio 1</h4>
<p>Classico esempio con &lt;map&gt; all&#8217;interno dell&#8217;oggetto, ed i tag &lt;a&gt; all&#8217;interno di &lt;map&gt;.</p>
<pre lang="html">&lt;HTML&gt;
	&lt;HEAD&gt;&lt;TITLE&gt;The cool site!&lt;/TITLE&gt;&lt;/HEAD&gt;
	&lt;BODY&gt;
	&lt;P&gt;&lt;OBJECT data="navbar1.gif" type="image/gif" usemap="#map1"&gt;
		&lt;MAP name="map1"&gt;
			Navigate the site:
			&lt;A href="guide.html" shape="rect" coords="0,0,118,28"&gt;Access Guide&lt;/a&gt; |
			&lt;A href="shortcut.html" shape="rect" coords="118,0,184,28"&gt;Go&lt;/A&gt; |
			&lt;A href="search.html" shape="circle" coords="184,200,60"&gt;Search&lt;/A&gt; |
			&lt;A href="top10.html" shape="poly" coords="276,0,276,28,100,200,50,50,276,0"&gt;Top Ten&lt;/A&gt;
		&lt;/MAP&gt;
	&lt;/OBJECT&gt;&lt;/P&gt;
	&lt;/BODY&gt;
&lt;/HTML&gt;</pre>
<h4>Esempio 2</h4>
<p>Come utilizzare la mappa richiamandola con usemap, senza inglobarla all&#8217;interno dei tag &lt;object&gt;.</p>
<pre lang="html">&lt;HTML&gt;
	&lt;HEAD&gt;&lt;TITLE&gt;The cool site!&lt;/TITLE&gt;&lt;/HEAD&gt;
	&lt;BODY&gt;
	&lt;P&gt;&lt;OBJECT data="navbar1.gif" type="image/gif" usemap="#map1"&gt;&lt;/OBJECT&gt;&lt;/P&gt;
	&lt;MAP name="map1"&gt;
		Navigate the site:
		&lt;A href="guide.html" shape="rect" coords="0,0,118,28"&gt;Access Guide&lt;/a&gt; |
		&lt;A href="shortcut.html" shape="rect" coords="118,0,184,28"&gt;Go&lt;/A&gt; |
		&lt;A href="search.html" shape="circle" coords="184,200,60"&gt;Search&lt;/A&gt; |
		&lt;A href="top10.html" shape="poly" coords="276,0,276,28,100,200,50,50,276,0"&gt;Top Ten&lt;/A&gt;
	&lt;/MAP&gt;
&lt;/HTML&gt;</pre>
<h4>Esempio 3</h4>
<p>Utilizzo degli elementi &lt;area&gt;.</p>
<pre lang="html">&lt;HTML&gt;
	&lt;HEAD&gt;&lt;TITLE&gt;The cool site!&lt;/TITLE&gt;&lt;/HEAD&gt;
	&lt;BODY&gt;
	&lt;P&gt;&lt;OBJECT data="navbar1.gif" type="image/gif" usemap="#map1"&gt;&lt;/OBJECT&gt;&lt;/P&gt;
	&lt;MAP name="map1"&gt;
		Navigate the site:
		&lt;AREA href="guide.html" alt="Access Guide" shape="rect" coords="0,0,118,28"&gt;
		&lt;AREA href="search.html" alt="Search" shape="rect" coords="184,0,276,28"&gt;
		&lt;AREA href="shortcut.html" alt="Go" shape="circle" coords="184,200,60"&gt;
		&lt;AREA href="top10.html" alt="Top Ten" shape="poly" coords="276,0,276,28,100,200,50,50,276,0"&gt;
	&lt;/MAP&gt;
&lt;/HTML&gt;</pre>
<h4>Esempio 4</h4>
<p>Questo è un utilizzo concreto della condivisione di una mappa fra più immagini. Questo codice carica l&#8217;immagine più interna (navbar1.gif) se l&#8217;immagine esterna (navbar1.png) non viene processata correttamente dal browser. Ad entrambe le immagini viene associata la stessa mappa.</p>
<pre lang="html">&lt;HTML&gt;
	&lt;HEAD&gt;&lt;TITLE&gt;The cool site!&lt;/TITLE&gt;&lt;/HEAD&gt;
	&lt;BODY&gt;
	&lt;P&gt;&lt;OBJECT data="navbar1.png" type="image/png" usemap="#map1"&gt;
		&lt;OBJECT data="navbar1.gif" type="image/gif" usemap="#map1"&gt;&lt;/OBJECT&gt;
	&lt;/OBJECT&gt;&lt;/P&gt;
	&lt;MAP name="map1"&gt;
		Navigate the site:
		&lt;A href="guide.html" shape="rect" coords="0,0,118,28"&gt;Access Guide&lt;/a&gt; |
		&lt;A href="shortcut.html" shape="rect" coords="118,0,184,28"&gt;Go&lt;/A&gt; |
		&lt;A href="search.html" shape="circle" coords="184,200,60"&gt;Search&lt;/A&gt; |
		&lt;A href="top10.html" shape="poly" coords="276,0,276,28,100,200,50,50,276,0"&gt;Top Ten&lt;/A&gt;
	&lt;/MAP&gt;
&lt;/HTML&gt;</pre>
<h4>Esempio 5</h4>
<p>Utilizzo combinato di &lt;area&gt; e &lt;a&gt; per avere una maggiore compatibilità. I browser più recenti non considerano gli elementi &lt;area&gt;.</p>
<pre lang="html">&lt;HTML&gt;
	&lt;HEAD&gt;&lt;TITLE&gt;The cool site!&lt;/TITLE&gt;&lt;/HEAD&gt;
	&lt;BODY&gt;
	&lt;P&gt;&lt;OBJECT data="navbar1.gif" type="image/gif" usemap="#map1"&gt;&lt;/OBJECT&gt;&lt;/P&gt;
	&lt;MAP name="map1"&gt;
		Navigate the site:
		&lt;AREA href="guide.html" alt="Access Guide" shape="rect" coords="0,0,118,28"&gt;
		&lt;AREA href="search.html" alt="Search" shape="rect" coords="184,0,276,28"&gt;
		&lt;AREA href="shortcut.html" alt="Go" shape="circle" coords="184,200,60"&gt;
		&lt;AREA href="top10.html" alt="Top Ten" shape="poly" coords="276,0,276,28,100,200,50,50,276,0"&gt;
		&lt;A href="guide.html" shape="rect" coords="0,0,118,28"&gt;Access Guide&lt;/a&gt; |
		&lt;A href="shortcut.html" shape="rect" coords="118,0,184,28"&gt;Go&lt;/A&gt; |
		&lt;A href="search.html" shape="circle" coords="184,200,60"&gt;Search&lt;/A&gt; |
		&lt;A href="top10.html" shape="poly" coords="276,0,276,28,100,200,50,50,276,0"&gt;Top Ten&lt;/A&gt;
	&lt;/MAP&gt;
&lt;/HTML&gt;</pre>
<h4>Esempio 6</h4>
<p>Come sovrapporre due aree. Da notare l&#8217;ultima coordinata specificata, il raggio). I due cerchi hanno lo stesso centro, ma il primo ha un raggio minore del secondo.</p>
<p>Il risultato è che posizionandosi sul primo (che non ha link) non appare la &#8220;manina&#8221;. Spostandosi leggermente fuori dal primo ci si posiziona sul secondo (che ha un link) ed appare la &#8220;manina&#8221;. In pratica, l&#8217;area specificata prima ha la <strong>precedenza</strong> sulle altre che sovrascrive.</p>
<pre lang="html">&lt;MAP name="map1"&gt;
	&lt;A shape="circle" coords="100,200,50"&gt;Non ho link&lt;/A&gt;
	&lt;A href="outer-ring-link.html" shape="circle" coords="100,200,250"&gt;Ho un link&lt;/A&gt;
&lt;/MAP&gt;</pre>
<h3>Image maps lato server</h3>
<p>A volte la mappatura delle immagini può essere <strong>troppo complicata</strong> da scrivere come html.</p>
<p>In questi casi è meglio ricorrere a tecniche lato server.</p>
<p>Partiamo dal <strong>codice html</strong>. Da notare l&#8217;attributo <strong>ismap</strong>.</p>
<pre lang="html">&lt;HTML&gt;
	&lt;HEAD&gt;&lt;TITLE&gt;The cool site!&lt;/TITLE&gt;&lt;/HEAD&gt;
	&lt;BODY&gt;
	&lt;A href="map_script.php"&gt;
		&lt;IMG src="navbar1.png" alt="Navigazione" ismap /&gt;
	&lt;/A&gt;
&lt;/HTML&gt;</pre>
<p><strong>Come funziona?</strong> Quando ci si posiziona sull&#8217;immagine, il browser aggiunge all&#8217;url di &lt;a&gt;, quindi a map_script.php, le due coordinate. Ad esempio, se ci posizioniamo sul pixel di coordinate (18,46), il link del tag &lt;a&gt; verrà<strong> trasformato automaticamente</strong> da map_script.php a map_script.php?18,46.</p>
<p>Lo <strong>script lato server</strong> ha il compito di leggere i <strong>due parametri $_GET</strong> relativi alle coordinate e comportarsi a seconda dei valori letti.</p>
<pre lang="php">&lt;?php
/* $_GET array associativo. Ottiene le chiavi dell'array. */
$keys = array_keys($_GET);

/* Prende la prima chiave, la divide e inserisce i due valori in $x e $y */
list($x,$y) = explode(",",$keys[0]);

/* Comportamenti */
if(($x&gt;=0 &amp;&amp; $x&lt;=118) &amp;&amp; ($y&gt;=0 &amp;&amp; $y&lt;=28))	 include("guide.html");
elseif(($x&gt;118 &amp;&amp; $x&lt;=184) &amp;&amp; ($y&gt;=0 &amp;&amp; $y&lt;=28)) include("shortcut.html");
elseif( ($x&gt;=(184-30) &amp;&amp; $x&lt;=(184+30)) &amp;&amp; ($y&gt;=(200-30) &amp;&amp; $y&lt;=(200+30)) ) include("search.html");
elseif(($x&gt;220 &amp;&amp; $x&lt;=280) &amp;&amp; ($y&gt;=30 &amp;&amp; $y&lt;=54)) include("top10.html");
?&gt;</pre>
<p>Nel codice dell&#8217;esempio 1, l&#8217;area relatva a <strong>top10.html</strong> è un poligono. Non è semplice controllare se un punto è presente in un poligono. Bisogna trovare e utilizzare appositi algoritmi e funzioni. Potresti trovarli su <a title="Geometry Algorithms" href="http://www.geometryalgorithms.com/" target="_blank">geometryalgorithms.com</a> (che nel momento in cui scrivo è &#8220;temporaneamente sospeso&#8221;).</p>
<h4>Script, demo e download</h4>
<p>Per vedere e scaricare lo script vai a <a href="http://test.jblog.it/imagemap_ss/map_script.txt" target="_blank">http://test.jblog.it/imagemap_ss/map_script.txt</a></p>
<p>Per vedere una demo vai a <a href="http://test.jblog.it/imagemap_ss/" target="_blank">http://test.jblog.it/imagemap_ss/</a></p>
<p>Per scaricare l&#8217;esempio vai a <a href="http://download.jblog.it/imagemap_ss.zip" target="_blank">http://download.jblog.it/imagemap_ss.zip</a></p>
<h3>Image maps lato client e lato server</h3>
<p>Per avere la compatibilità con i vecchi browser è bene combinare le due tecniche.</p>
<pre lang="html">&lt;HTML&gt;
	&lt;HEAD&gt;&lt;TITLE&gt;The cool site!&lt;/TITLE&gt;&lt;/HEAD&gt;
	&lt;BODY&gt;
	&lt;A href="map_script.php"&gt;
		&lt;IMG src="navbar1.gif" alt="Navigazione" usemap="#map1" ismap /&gt;
	&lt;/A&gt;
	&lt;MAP name="map1"&gt;
		Navigate the site:
		&lt;A href="guide.html" shape="rect" coords="0,0,118,28"&gt;Access Guide&lt;/a&gt; |
		&lt;A href="shortcut.html" shape="rect" coords="118,0,184,28"&gt;Go&lt;/A&gt; |
		&lt;A href="search.html" shape="circle" coords="184,200,60"&gt;Search&lt;/A&gt; |
		&lt;A href="top10.html" shape="poly" coords="276,0,276,28,100,200,50,50,276,0"&gt;Top Ten&lt;/A&gt;
	&lt;/MAP&gt;
	&lt;/BODY&gt;
&lt;/HTML&gt;</pre>
<h3>Il testo alternativo</h3>
<p>I tag &lt;a&gt; con il testo all&#8217;interno si utilizzano per avere un testo alternativo nel caso in cui l&#8217;immagine non venga caricata.</p>
<p>Naturalmente questo comportamento non è gestito dal browser, infatti il testo dei link appare sempre.</p>
<p><strong>Per nasconderlo</strong> è necessario operare con i css. Consiglio anche di guardare le tecniche di &#8220;image replacement&#8221;.</p>
<h4>Script, demo e download</h4>
<p>Per vedere lo script vai a <a href="http://test.jblog.it/imagemap_css/map_script.txt" target="_blank">http://test.jblog.it/imagemap_css/map_script.txt</a></p>
<p>Per vedere una demo vai a <a href="http://test.jblog.it/imagemap_css/" target="_blank">http://test.jblog.it/imagemap_css/</a></p>
<p>Per scaricare l&#8217;esempio vai a <a href="http://download.jblog.it/imagemap_css.zip" target="_blank">http://download.jblog.it/imagemap_css.zip</a></p>
<h2>Lo schema data:URL</h2>
<p>Questa tecnica permette di <strong>inserire i dati direttamente nel codice html</strong>, risparmiando quindi la relativa richiesta http.</p>
<p>Scopriamo le carte e vediamo subito un <strong>esempio</strong>.</p>
<pre lang="html">&lt;IMG ALT="Foto" SRC="data:image/gif; base64,
	R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwhhx4dbgYKAAA7B72VFgl2Tf7452
	AAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFz
	ByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSp
	a/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJl
	ZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uis
	F81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PH" /&gt;</pre>
<p>Dopo la paura iniziale, in genere ci si domanda: <strong>cosa sono quei caratteri e come faccio a inserirli?</strong></p>
<p>Quell&#8217;ammasso di caratteri è la <strong>codifica in base64</strong> dell&#8217;immagine. In pratica, è il contenuto del file immagine codificato in base64.</p>
<p>Per<strong> codificare un&#8217;immagine in base64</strong> si utilizza una semplice <strong>funzione php</strong>: <em>base64_encode</em>.</p>
<p>L&#8217;ultima questione riguarda il tipo <strong>MIME</strong> che si può ottenere in due modi:</p>
<ul>
<li>utilizzando la funzione <strong>mime_content_type</strong>. Deve essere abilitata l&#8217;<strong>estensione php_mime_magic.dll</strong>.</li>
<li>leggendo le informazioni su un file grazie le funzioni <a title="File Information" href="http://it2.php.net/manual/en/book.fileinfo.php"><strong>File Information</strong></a> di php. Era un&#8217;estensione PECL, ma ora non lo è più. Bisogna utilizzare la <strong>libreria esterna magic_open</strong></li>
</ul>
<p>Nel caso non si possano utilizzare queste funzioni si dovrà <strong>scrivere manualmente</strong>.</p>
<h4>Come inserire un&#8217;immagine in base64 (senza funzioni per il tipo MIME)</h4>
<pre>&lt;img src="data:image/jpeg;base64,&lt;?
echo base64_encode(file_get_contents("img.jpg")); ?&gt;" alt="Immagine" /&gt;</pre>
<h4>Come inserire un&#8217;immagine in base64 (con funzioni per il tipo MIME)</h4>
<pre>&lt;? $mime = mime_content_type("img.jpg"); ?&gt;
&lt;img src="data:&lt;? echo $mime; ?&gt;;base64,&lt;?
echo base64_encode(file_get_contents("img.jpg")); ?&gt;" alt="Immagine" /&gt;</pre>
<h4>Script, demo e download</h4>
<p>Per vedere lo script vai a <a href="http://test.jblog.it/img_base64/index.txt" target="_blank">http://test.jblog.it/img_base64/index.txt</a><a href="http://test.jblog.it/imagemap_css/map_script.txt" target="_blank"></a></p>
<p>Per vedere una demo vai a <a href="http://test.jblog.it/img_base64/" target="_blank">http://test.jblog.it/img_base64/</a></p>
<p>Per scaricare l&#8217;esempio vai a <a href="http://download.jblog.it/img_base64.zip" target="_blank">http://download.jblog.it/img_base64.zip</a></p>
<h2>Gli sprite CSS</h2>
<p><img class="alignright size-full wp-image-453" title="Icone per webdesigner" src="http://jblog.it/wp-content/uploads/2009/05/developpers_icons_preview2.jpg" alt="Icone per webdesigner" width="282" height="140" />Partiamo dalla situazione più comune. Supponiamo di voler realizzare un menù composto da 5 pulsanti grafici che cambino colore quando si passa sopra col mouse. La cosa più logica sarebbe quella di creare 10 immagini: 5 per il pulsante in modalita &#8220;normale&#8221;, 5 per il pulsante in modalità &#8220;mouse sopra&#8221;.</p>
<p>Poiché caricare 10 immagini significa effettuare <strong>10 richieste http</strong>, utilizziamo la tecnica degli sprite CSS.</p>
<p><strong>Questa tecnica</strong> consiste nel:</p>
<ul>
<li>creare un file immagine abbastanza grande da contenere tutte e 10 le immagini del menù (come ho detto all&#8217;inizio dell&#8217;articolo, è meglio un&#8217;immagine grande anziché tante piccole immagini)</li>
<li>impostare questa immagine come sfondo agli elementi del menù (cioè &lt;a&gt;, &lt;li&gt;, &lt;div&gt;, ecc.)</li>
<li>per ogni elemento impostare la proprietà <strong>background-position</strong> per spostare lo sfondo all&#8217;interno dell&#8217;elemento in modo da avere l&#8217;immagine desiderata</li>
</ul>
<p>Gli <strong>utilizzi </strong>di questa tecnica sono infiniti: dal menù al singolo rollover, dalla serie di immagini allineate al contenitore con gli angoli arrotondati.</p>
<p><strong>VANTAGGI</strong></p>
<ul>
<li>riduce notevolmente le <strong>richieste http</strong> e migliora il caricamento delle pagine</li>
<li>elimina del tutto i <strong>ritardi </strong>relativi ai rollover poiché non viene caricata una nuova immagine ma viene spostato lo sfondo</li>
</ul>
<p><strong>SVANTAGGI</strong></p>
<ul>
<li>richiede un po&#8217; più di <strong>lavoro </strong>nell&#8217;impostazione dei css e nella creazione delle immagini</li>
<li>non è sempre possibile combinare in una sola immagine tutte le immagini del sito, a causa delle difficoltà che si incontrano nel <strong>posizionamento dello sfondo</strong> con le regole dei css</li>
</ul>
<h4>Esempio 1</h4>
<p>Inserire le immagini con il <strong>tag &lt;img&gt;</strong>. Questo metodo è a dir poco geniale poiché permette di inserire le immagini come si è sempre fatto col vantaggio di ridurre le richieste http. In pratica viene impostato lo <strong>sfondo al tag &lt;img&gt;</strong>.</p>
<p>L&#8217;articolo completo è di <a title="CssGlobe" href="http://cssglobe.com/" target="_blank">CssGlobe</a>. Lo puoi trovare <a title="Creating easy and useful CSS Sprites" href="http://cssglobe.com/post/3028/creating-easy-and-useful-css-sprites" target="_blank">qui</a>.</p>
<p>Abbiamo bisogno di un&#8217;immagine gif trasparente 1px x 1px (spacer.gif), e l&#8217;immagine sprite (tuttelefoto.jpg).</p>
<p><img class="size-full wp-image-429 alignnone" title="tuttelefoto.jpg - Immagine utilizzata come sfondo degli elementi" src="http://jblog.it/wp-content/uploads/2009/05/tuttelefoto.jpg" alt="tuttelefoto Ridurre le richieste HTTP (parte 2): come unire e combinare immagini, script, css" width="210" height="140" /></p>
<p><em>tuttelefoto.jpg &#8211; L&#8217;immagine sprite che utilizzeremo</em></p>
<pre lang="html">&lt;html&gt;
&lt;head&gt;&lt;title&gt;Sprite CSS - Esempio 1&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;
	&lt;img src="spacer.gif" id="foto1" alt="Foto1" /&gt;
	&lt;img src="spacer.gif" id="foto2" alt="Foto2" /&gt;
	&lt;img src="spacer.gif" id="foto3" alt="Foto3" /&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>L&#8217;immagine trasparente serve per far assumere al tag &lt;img&gt; il suo normale comportamento (ad es. in modo che quando selezioni l&#8217;immagine si colora l&#8217;area di &lt;img&gt;).</p>
<p><strong>Codice css</strong></p>
<pre lang="css">#foto1, #foto2, #foto3 { background:url(tuttelefoto.jpg) no-repeat; }
#foto1 { width:100px; height:50px; background-position:0px 0px; }
#foto2 { width:120px; height:90px; background-position:0px -50px; }
#foto3 { width:90px; height:130px; background-position:-120px 0px; }</pre>
<p><strong>Demo e download</strong></p>
<p>Per vedere una demo vai a <a href="http://test.jblog.it/img_sprite1/" target="_blank">http://test.jblog.it/img_sprite1/</a><a href="http://test.jblog.it/img_base64/" target="_blank"></a></p>
<p>Per scaricare l&#8217;esempio vai a <a href="http://download.jblog.it/img_sprite1.zip" target="_blank">http://download.jblog.it/img_sprite1.zip</a><a href="http://download.jblog.it/img_base64.zip" target="_blank"></a></p>
<h4>Esempio 2</h4>
<p>Un&#8217;altro modo per inserire delle immagini è impostarle come sfondo ad elementi flottanti.</p>
<p><img class="size-full wp-image-431 alignnone" title="spriteimg" src="http://jblog.it/wp-content/uploads/2009/05/spriteimg.png" alt="spriteimg Ridurre le richieste HTTP (parte 2): come unire e combinare immagini, script, css" width="150" height="80" /></p>
<p><em>spriteimg.png &#8211; L&#8217;immagine sprite che utilizzeremo</em></p>
<pre lang="html">&lt;html&gt;
&lt;head&gt;&lt;title&gt;Sprite CSS - Esempio 2&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;
	&lt;a href="#" id="feedburner"&gt;&lt;/a&gt;
	&lt;a href="#" id="subscribe"&gt;&lt;/a&gt;
	&lt;a href="#" id="bookmarks"&gt;&lt;/a&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p><strong>Demo e download</strong></p>
<p>Per vedere una demo vai a <a href="http://test.jblog.it/img_sprite2/" target="_blank">http://test.jblog.it/img_sprite2/</a></p>
<p>Per scaricare l&#8217;esempio vai a <a href="http://download.jblog.it/img_sprite2.zip" target="_blank">http://download.jblog.it/img_sprite2.zip</a></p>
<p><strong>Codice css</strong></p>
<pre lang="css">#feedburner { margin-right:20px; background:url(spriteimg.png) no-repeat -5px -5px; float:left; width:91px; height:29px; }
#subscribe { margin-right:20px; background:url(spriteimg.png) no-repeat -5px -35px; float:left; width:127px; height:18px; }
#bookmarks { background:url(spriteimg.png) no-repeat -5px -55px; float:left; width:127px; height:18px; }</pre>
<h4>Esempio 3</h4>
<p>Gli sprite css sono ideali per sviluppare menù di navigazione.</p>
<p><img class="size-full wp-image-432 alignnone" title="spriteimg1" src="http://jblog.it/wp-content/uploads/2009/05/spriteimg1.png" alt="spriteimg1 Ridurre le richieste HTTP (parte 2): come unire e combinare immagini, script, css" width="700" height="60" /></p>
<p><em>spritemenu.png &#8211; L&#8217;immagine sprite che utilizzeremo</em></p>
<pre lang="html">&lt;html&gt;
&lt;head&gt;&lt;title&gt;Sprite CSS - Esempio 3&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;
	&lt;ul id="navmenu"&gt;
		&lt;li id="nav_homepage"&gt;&lt;a href="#"&gt;&lt;/a&gt;&lt;/li&gt;
		&lt;li id="nav_informazioni"&gt;&lt;a href="#"&gt;&lt;/a&gt;&lt;/li&gt;
		&lt;li id="nav_catalogo"&gt;&lt;a href="#"&gt;&lt;/a&gt;&lt;/li&gt;
		&lt;li id="nav_indirizzi"&gt;&lt;a href="#"&gt;&lt;/a&gt;&lt;/li&gt;
		&lt;li id="nav_contact"&gt;&lt;a href="#"&gt;&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p><strong>Codice css</strong></p>
<pre lang="css">#navmenu ul { list-style:none; }
#navmenu li { float:left; list-style:none; }
#navmenu a { display:block; height:30px; width:135px; background:url(spritemenu.png) no-repeat;  }

#nav_homepage a:link, #nav_homepage a:visited { background-position:0px 0px; }
#nav_informazioni a:link, #nav_informazioni a:visited { background-position:-270px 0px; }
#nav_catalogo a:link, #nav_catalogo a:visited { background-position:-560px 0px; }
#nav_indirizzi a:link, #nav_indirizzi a:visited { background-position:-420px 0px; }
#nav_contact a:link, #nav_contact a:visited { background-position:-135px 0px; }

#nav_homepage a:hover, #nav_homepage a:focus, #nav_homepage a:active { background-position:0px -30px; }
#nav_informazioni a:hover, #nav_informazioni a:focus, #nav_informazioni a:active { background-position:-270px -30px; }
#nav_catalogo a:hover, #nav_catalogo a:focus, #nav_catalogo a:active { background-position:-560px -30px; }
#nav_indirizzi a:hover, #nav_indirizzi a:focus, #nav_indirizzi a:active { background-position:-420px -30px; }
#nav_contact a:hover, #nav_contact a:focus, #nav_contact a:active { background-position:-135px -30px; }</pre>
<p><strong>Demo e download</strong></p>
<p>Per vedere una demo vai a <a href="http://test.jblog.it/img_sprite3/" target="_blank">http://test.jblog.it/img_sprite3/</a></p>
<p>Per scaricare l&#8217;esempio vai a <a href="http://download.jblog.it/img_sprite3.zip" target="_blank">http://download.jblog.it/img_sprite3.zip</a></p>
<h2>Generatori di Sprite CSS</h2>
<p>I generatori di sprite css <strong>semplificano la creazione</strong> di un&#8217;immagine abbastanza grande da contenere tutte le immagini da utilizzare nel proprio sito. Questi, secondo me, sono i migliori.</p>
<p><strong>Generatore di Sprite CSS</strong><br />
<a href="http://spritegen.website-performance.org/" target="_blank">http://spritegen.website-performance.org/</a><br />
<a href="https://launchpad.net/css-sprite-generator" target="_blank">https://launchpad.net/css-sprite-generator</a> <em><strong>(codice sorgente)</strong></em></p>
<p><strong>CSS Sprites Generator</strong><br />
<a href="http://www.csssprites.com/" target="_blank">http://www.csssprites.com/</a></p>
<p><strong>CSS sprites for humanoid beings (and the like)</strong><br />
<a href="http://printf.ru/spritr/" target="_blank">http://printf.ru/spritr/</a></p>
<p><strong>SmartSprites (Alpha!)</strong><br />
<a href="http://smartsprites.osinski.name/" target="_blank">http://smartsprites.osinski.name/</a></p>
<h2>Combinare javascript e css</h2>
<p><img class="alignright size-full wp-image-445" title="Cubetti di legno" src="http://jblog.it/wp-content/uploads/2009/05/288478628_56ed41bc2c.jpg" alt="Cubetti di legno" width="270" height="405" />Spesso una pagina richiama <strong>più di uno script e più di un css</strong>. Per ridurre le richieste http relative ai css (o agli script) basta copiare il contenuto di tutti i file css (o script) in un unico file.</p>
<p>Il bello di questa tecnica è che, a differenza delle immagini, è quasi sempre possibile <strong>combinare tutti i file dello stesso tipo in un unico file</strong>. Il &#8220;quasi&#8221; è dovuto al fatto che alcuni script, se inseriti nello stesso file, potrebbero dare dei problemi. Quindi è sempre meglio testare il funzionamento dello script combinato. Se si verificano dei problemi, basta <strong>escludere dalla fusione</strong> i file &#8220;incompatibili&#8221;.</p>
<p>La combinazione degli script in un unico file può essere eseguita in due modi:</p>
<ul>
<li><strong>manualmente</strong>, cioé copiando il contenuto di ogni script all&#8217;interno di un file più grande</li>
<li><strong>dinamicamente</strong>, ricorrendo a semplici script lato server</li>
</ul>
<p>Gli <strong>script lato server</strong> che vedremo sono strutturati in <strong>5 fasi</strong>:</p>
<ul>
<li>lettura dei nomi dei file da includere passati come parametri $_GET</li>
<li>impostazione delle opzioni</li>
<li>inclusione effettiva dei file</li>
<li>stampa dei campi di intestazione con la funzione header() per la gestione della cache, il tipo mime, ETag</li>
<li>stampa del contenuto finale del file</li>
</ul>
<h3>Script php: combinare più file css</h3>
<p>La particolarità dello script relativo ai file css è che per ogni file da includere è necessario <strong>specificare l&#8217;attributo media</strong> (all, screen, print, ecc.), cioé quell&#8217;attributo che indica il tipo di dispositivo per cui deve valere quel file css. <strong>Non è necessario specificare l&#8217;estensione</strong> dei file poiché viene aggiunta automaticamente all&#8217;interno dello script.</p>
<p><strong>Attenzione.</strong> Non passare nomi di file contenenti il carattere &#8220;.&#8221; in quanto, nelle richieste $_GET, viene convertito automaticamente in &#8220;_&#8221;.</p>
<p><strong>Codice html</strong></p>
<pre lang="html">&lt;link rel="stylesheet" type="text/css"
href="combined.css?file1:all&amp;file2:screen&amp;file3:print" /&gt;</pre>
<p><strong>Impostare Apache</strong></p>
<p>Poiché lo script che ha l&#8217;estensione <strong>.css</strong> è necessario impostare il server Apache affinché processi il file combined.css come un file .php. Basterà aggiungere un paio di righe.</p>
<pre>&lt;FilesMatch "combined.css$"&gt;
	AddHandler application/x-httpd-php .css
&lt;/FilesMatch&gt;</pre>
<h4>Script, demo e download</h4>
<p>Per vedere lo script vai a <a href="http://test.jblog.it/combine_css/combine.txt" target="_blank">http://test.jblog.it/combine_css/combine.txt</a></p>
<p>Per vedere una demo vai a <a href="http://test.jblog.it/combine_css/combine.css?file1:all&amp;file2:screen&amp;file3:print" target="_blank">http://test.jblog.it/combine_css/combine.css?file1:all&amp;file2:screen&amp;file3:print</a></p>
<p>Per scaricare l&#8217;esempio vai a <a href="http://download.jblog.it/combine_css.zip" target="_blank">http://download.jblog.it/combine_css.zip</a></p>
<h3>Script php: combinare più file javascript</h3>
<p><strong>Non è necessario specificare l&#8217;estensione</strong> dei file poiché viene aggiunta automaticamente all&#8217;interno dello script.</p>
<p><strong>Attenzione.</strong> Non passare nomi di file contenenti il carattere &#8220;.&#8221; in quanto, nelle richieste $_GET, viene convertito automaticamente in &#8220;_&#8221;.</p>
<h4>Codice html</h4>
<pre lang="html">&lt;script type="application/javascript" src="combined.js?file1&amp;file2&amp;file3"&gt;&lt;/script&gt;</pre>
<h4>Impostare Apache</h4>
<p>Poiché lo script che ha l&#8217;estensione <strong>.js</strong> è necessario impostare il server Apache affinché processi il file combined.js come un file .php. Basterà aggiungere un paio di righe.</p>
<pre>&lt;FilesMatch "combined.js$"&gt;
	AddHandler application/x-httpd-php .js
&lt;/FilesMatch&gt;</pre>
<h4>Script, demo e download</h4>
<p>Per vedere lo script vai a <a href="http://test.jblog.it/combine_js/combine.txt" target="_blank">http://test.jblog.it/combine_js/combine.txt</a></p>
<p>Per vedere una demo vai a <a href="http://test.jblog.it/combine_js/combine.js?file1&amp;file2&amp;file3" target="_blank">http://test.jblog.it/combine_js/combine.js?file1&amp;file2&amp;file3</a></p>
<p>Per scaricare l&#8217;esempio vai a <a href="http://download.jblog.it/combine_js.zip" target="_blank">http://download.jblog.it/combine_js.zip</a></p>
<h2>Stampare javascript e css nel codice html</h2>
<p>Sappiamo che per utilizzare codice javascript o css ci sono 3 modi:</p>
<ol>
<li>stamparli direttamente nel codice html</li>
<li>dividerli su più file esterni (da richiamare)</li>
<li>stamparne alcuni e richiamare gli altri</li>
</ol>
<h4>Il terzo metodo</h4>
<p>Come succede in tante occasioni, la &#8220;via di mezzo&#8221; è da preferire. La successiva domanda è: <strong>su che criterio si scelgono</strong> i file da stampare nel codice html e quelli da richiamare esternamente?</p>
<p>Sinceramente, non saprei dirlo con precisione. Probabilmente esistono degli studi che potrebbero aiutarti in questo. Secondo me, il codice da stampare nel documento html è quello che presumibilmente <strong>potrebbe essere utilizzato prima</strong>. Ad esempio:</p>
<ul>
<li>per <strong>javascript</strong>, il codice e le funzioni che verranno eseguite nell&#8217;<strong>evento &#8220;onload&#8221; dell&#8217;oggetto &#8220;document&#8221;</strong></li>
<li>per i <strong>css</strong>, il codice che serve a formattare gli <strong>elementi principali della pagina</strong>, come html, layout, contenitori, ecc.</li>
</ul>
<h4>Come automatizzare il tutto</h4>
<p>Fortunatamente, questa tecnica si può automatizzare con un paio di righe di codice lato server (php).</p>
<pre lang="html">&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Javascript e Css nella pagina&lt;/title&gt;

&lt;style type="text/css"&gt;
&lt;?
	/* Array dei file css */
	$css_array = array("file3.css","file2.css");
	foreach($css_array as $css)
	{
		if(file_exists($css))
		include($css);
		echo "\n\n";
	}
?&gt;
&lt;/style&gt;

&lt;script type="application/javascript"&gt;
//&lt;![CDATA[
&lt;?
	/* Array dei javascript */
	$js_array = array("file1.js","file3.js");
	foreach($js_array as $js)
	{
		if(file_exists($js))
		include($js);
		echo "\n\n";
	}
?&gt;
//]]&gt;
&lt;/script&gt;

&lt;!-- File css esterni --&gt;
&lt;link rel="stylesheet" type="text/css" href="file1.css" /&gt;

&lt;!-- File javascript esterni --&gt;
&lt;script type="application/javascript" src="file2.js"&gt;&lt;/script&gt;

&lt;/head&gt;
&lt;body&gt;
	&lt;h1&gt;Javascript e Css nella pagina&lt;/h1&gt;
	&lt;p&gt;Guarda il codice html&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<h4>Script, demo e download</h4>
<p>Per vedere lo script vai a <a href="http://test.jblog.it/inhtml/inhtml.txt" target="_blank">http://test.jblog.it/inhtml/inhtml.txt</a></p>
<p>Per vedere una demo vai a <a href="http://test.jblog.it/inhtml/" target="_blank">http://test.jblog.it/inhtml/</a></p>
<p>Per scaricare l&#8217;esempio vai a <a href="http://download.jblog.it/inhtml.zip" target="_blank">http://download.jblog.it/inhtml.zip</a></p>
<h2>Eliminare gli script duplicati</h2>
<p><img class="alignright size-full wp-image-446" title="Do not duplicate" src="http://jblog.it/wp-content/uploads/2009/05/331357312_893ef9e791.jpg" alt="Do not duplicate" width="270" height="180" />Quando si gestiscono <strong>grandi progetti</strong> si rischia di stampare e richiamare gli stessi script.</p>
<p>Alcuni browser, come Firefox, evitano di effettuare una nuova richiesta http per un file che è stato già scaricato. Purtroppo Internet Explorer non lo fa. Allora è necessario trovare una soluzione che valga per tutti.</p>
<p>Una semplice soluzione consiste nel fare una <strong>funzione php </strong>che riceva il nome del file da linkare e si occupi di stampare i tag &lt;script&gt;. Per registrare gli script che vengono inseriti di volta in volta si utilizza un array in modo che la funzione, prima di inserire uno script, controlla se il nome dello script non è già presente nell&#8217;array.</p>
<p>Normalmente per inserire script e css si dovrebbe scrivere:</p>
<pre>&lt;link rel="stylesheet" type="text/css" href="print_style.css" media="print" /&gt;
&lt;script src="library.js" type="application/javascript"&gt;&lt;/script&gt;</pre>
<p><strong>Classe PHP: noDuplicate (per php 4 e php 5)<br />
</strong></p>
<p>Ti descrivo brevemente la classe &#8220;noDuplicate&#8221;.</p>
<p><strong>La struttura</strong></p>
<pre lang="php">class noDuplicate
{
	/* Array dei file javascript */
	var $js_array = array();

	/* Array dei file css */
	var $css_array = array();

	/* Stampa i file specificati. */
	function incScript() { ... }

	/* Privata: registra il file e stampa il link al file javascript */
	function __js($file) { ... }

	/* Privata: registra il file stampa il link al file css */
	function __css($file) { ... }
}</pre>
<p><strong>Creare l&#8217;oggetto</strong></p>
<pre lang="php">$noDuplicateObj = new noDuplicate();</pre>
<p><strong>La funzione incScript()</strong></p>
<ul>
<li>il primo argomento deve essere &#8220;js&#8221; o &#8220;css&#8221;</li>
<li>dal secondo argomento in poi accetta da uno a più file <strong>dello stesso tipo</strong></li>
<li>se si devono inserire file <strong>.css</strong> è necessario passarli nella forma [nomefile]:[media] (ad es. &#8220;style.css:print&#8221;). Se vengono passati nella forma normale (&#8220;style.css&#8221;,&#8221;file.css&#8221;) verrà automaticamente impostato &#8220;all&#8221; come media</li>
</ul>
<pre lang="php">// singolo file
$noDuplicate-&gt;incScript("css","file2.css:all");
$noDuplicate-&gt;incScript("js","file1.js");

// più di un file
$noDuplicate-&gt;incScript("css","file2.css:all","mystyle.css:screen");
$noDuplicate-&gt;incScript("js","file1.js","jquery.js","prototype.js");

// file css senza specificare il "media"
$noDuplicate-&gt;incScript("css","file1.css","file3.css");<strong>
</strong></pre>
<p><strong>Risultato</strong></p>
<pre lang="html">&lt;!-- singolo file --&gt;
&lt;link rel="stylesheet" type="text/css" href="file2.css" media="all" /&gt;
&lt;script src="file1.js" type="application/javascript"&gt;&lt;/script&gt;

&lt;!-- più di un file --&gt;
&lt;link rel="stylesheet" type="text/css" href="file2.css" media="all" /&gt;
&lt;link rel="stylesheet" type="text/css" href="mystyle.css" media="screen" /&gt;
&lt;script src="file1.js" type="application/javascript"&gt;&lt;/script&gt;
&lt;script src="jquery.js" type="application/javascript"&gt;&lt;/script&gt;
&lt;script src="prototype.js" type="application/javascript"&gt;&lt;/script&gt;

&lt;!-- file css senza specificare il "media" --&gt;
&lt;link rel="stylesheet" type="text/css" href="file1.css" media="all" /&gt;
&lt;link rel="stylesheet" type="text/css" href="file3.css" media="all" /&gt;</pre>
<h4>Script, demo e download</h4>
<p>Per vedere lo script vai a <a href="http://test.jblog.it/rem_duplicate/rem_duplicate.txt" target="_blank">http://test.jblog.it/rem_duplicate/rem_duplicate.txt</a></p>
<p>Per vedere una demo vai a <a href="http://test.jblog.it/rem_duplicate/" target="_blank">http://test.jblog.it/rem_duplicate/</a></p>
<p>Per scaricare l&#8217;esempio vai a <a href="http://download.jblog.it/rem_duplicate.zip" target="_blank">http://download.jblog.it/rem_duplicate.zip</a></p>
<h2>Conclusione</h2>
<p>Queste tecniche esprimono la massima utilità e potenza se utilizzate contemporaneamente. La riduzione di richieste http e, quindi, l&#8217;abbassamento dei tempi di caricamento saranno notevoli.</p>
<p>Spero di essere stato abbastanza esaustivo e chiaro. Se non lo sono stato basterà dirmelo in modo da ritoccare l&#8217;articolo nelle sezioni meno comprensibili.</p>
<p><span class="hightlight_green">Hai mai utilizzato una di queste tecniche? Gli script hanno funzionato correttamente? È stato semplice metterle in pratica? Hai avuto concreti miglioramenti?</span></p>
<h3>Prossimo appuntamento</h3>
<p>L&#8217;ultima questione sull&#8217;ottimizzazione dei siti web riguarda appunto l&#8217;ottimizzazione dei componenti da caricare cioé:</p>
<ul>
<li>compressione delle immagini, degli script e dei css</li>
<li>offuscamento del codice javascript</li>
<li>utilizzo di gzip per la compressione delle pagine html, script e css</li>
</ul>
<h4 class="highlight_red">Non perdere il prossimo articolo sull&#8217;ottimizzazione dei componenti delle pagine web: codice html, immagini, script e css.</h4>
<h2>Crediti</h2>
<ul>
<li><strong>Libro</strong>. Creare siti web ad alte prestazioni di <a href="http://stevesouders.com" target="_blank">Steve Soulders</a></li>
<li><a href="http://www.websiteoptimization.com" target="_blank">WebSiteOptimization</a> &#8211; <a href="http://www.websiteoptimization.com/speed/tweak/combine/" target="_blank">Combine Images to Save HTTP Requests</a></li>
<li><a href="http://developer.yahoo.com/" target="_blank">Yahoo Developer Network</a> &#8211; <a href="http://developer.yahoo.com/performance/rules.html" target="_blank">Best Practices for Speeding Up Your Web Site</a></li>
<li><a href="http://www.w3.org">W3C</a> &#8211; <a href="http://www.w3.org/TR/html401/struct/objects.html#h-13.6" target="_blank">Objects, Images, and Applets: Image maps</a></li>
<li><a href="http://www.ietf.org/" target="_blank">The Internet Engineering Task Force</a> &#8211; <a href="http://tools.ietf.org/html/rfc2397" target="_blank">The &#8220;data&#8221; URL scheme</a></li>
<li><a href="http://cssglobe.com/" target="_blank">CssGlobe</a> &#8211; <a href="http://cssglobe.com/post/3028/creating-easy-and-useful-css-sprites" target="_blank">Creating easy and useful CSS Sprites</a></li>
<li>Foto1: <a href="http://www.flickr.com/photos/jasephotos/2913134974/" target="_blank">Mast Farm Picnic</a> &#8211; 030 di <a href="http://www.flickr.com/photos/jasephotos/" target="_blank">JasonBechtel</a></li>
<li>Foto2: <a href="http://olimpiadi.blogosfere.it/2008/08/davide-rebellin-argento-la-prima-medaglia-italiana-di-queste-olimpiadi.html" target="_blank">Davide Rebellin Argento, la prima medaglia italiana di queste Olimpiadi</a> di <a href="http://olimpiadi.blogosfere.it/" target="_blank">olimpiadi.blogosfere.it</a></li>
<li>Foto3: <a href="http://www.flickr.com/photos/kaibara/312855876/" target="_blank">Cats Puzzle</a> di <a href="http://www.flickr.com/photos/kaibara/" target="_blank">kaibara87</a></li>
<li>Foto4: <a href="http://elementiks.com/downloads/developpers_icons_preview.jpg" target="_blank">icone per sviluppatori</a></li>
<li>Foto5: <a href="http://www.flickr.com/photos/egansnow/288478628/" target="_blank">Puzzle</a> di <a href="http://www.flickr.com/photos/egansnow/" target="_blank">Egan Snow</a></li>
<li>Foto6: <a href="http://www.flickr.com/photos/popilop/331357312/" target="_blank">Do not duplicate</a> di <a href="http://www.flickr.com/photos/popilop/">Sam UL</a></li>
</ul>
<img src="http://jblog.it/?ak_action=api_record_view&id=405&type=feed" alt=" Ridurre le richieste HTTP (parte 2): come unire e combinare immagini, script, css"  title="Ridurre le richieste HTTP (parte 2): come unire e combinare immagini, script, css" />]]></content:encoded>
			<wfw:commentRss>http://jblog.it/2009/05/15/ridurre-richieste-http-parte-2-come-combinare-immagini-script-css-sprite-image-maps_405.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Come utilizzare Ajax: librerie, framework, ottimizzazione, caching, usabilità</title>
		<link>http://jblog.it/2009/05/02/come-utilizzare-ajax-basi-librerie-framework-ottimizzazione-caching-usabilita_202.html</link>
		<comments>http://jblog.it/2009/05/02/come-utilizzare-ajax-basi-librerie-framework-ottimizzazione-caching-usabilita_202.html#comments</comments>
		<pubDate>Sat, 02 May 2009 09:39:15 +0000</pubDate>
		<dc:creator>Giacomo</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Ottimizzazione]]></category>
		<category><![CDATA[Usabilità]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[classi librerie]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[mootools]]></category>
		<category><![CDATA[ottimizzare]]></category>
		<category><![CDATA[prototype]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[xmlhttprequest]]></category>

		<guid isPermaLink="false">http://jblog.it/?p=202</guid>
		<description><![CDATA[
Ajax è una tecnica di programmazione (non un linguaggio) che ti permette di sviluppare applicazioni web interattive. In pratica, grazie ad Ajax puoi aggiornare alcuni dati della pagina senza ricaricare completamente la pagina, migliorando le prestazioni del tuo sito.
In questo articolo: effettuare le richieste e gestire le risposte, formati per lo scambio dati, utilizzare librerie [...]]]></description>
			<content:encoded><![CDATA[<p><a title="Come utilizzare Ajax: libreria, framework, ottimizzazione, caching, usabilità" rel="attachment wp-att-375" href="http://jblog.it/2009/05/02/come-utilizzare-ajax-basi-librerie-framework-ottimizzazione-caching-usabilita_202.html/18xokt04_ajax_logo_150_rgb" target="_self"><img class="alignright size-full wp-image-375" title="Ajax logo" src="http://jblog.it/wp-content/uploads/2009/05/18xokt04_ajax_logo_150_rgb.jpg" alt="Ajax logo" width="157" height="140" /></a></p>
<p>Ajax è una tecnica di programmazione (non un linguaggio) che ti permette di sviluppare applicazioni web interattive. In pratica, grazie ad Ajax puoi aggiornare alcuni dati della pagina senza ricaricare completamente la pagina, migliorando le prestazioni del tuo sito.</p>
<p><span class="highlight_yellow"><strong>In questo articolo</strong>: effettuare le richieste e gestire le risposte, formati per lo scambio dati, utilizzare librerie e framework javascript, memorizzare Ajax in cache, evitare risposte duplicate, migliorare l&#8217;usabilità delle applicazioni ajax.</span></p>
<p><span id="more-202"></span></p>
<p><strong>Il termine &#8220;Ajax&#8221; è l&#8217;acronimo di Asynchronous JavaScript and XML.</strong></p>
<p>Vedremo che, nonostante la tecnica Ajax preveda l&#8217;utilizzo di XML, si potranno utilizzare altri formati per lo scambio dati.</p>
<p>Il termine &#8220;Ajax&#8221; è stato coniato da <a href="http://www.jjg.net/" target="_blank">Jesse James Garret</a> nel post &#8220;<a href="http://www.adaptivepath.com/ideas/essays/archives/000385.php" target="_blank">Ajax: A New Approach to Web Applications</a>&#8220;, il 18 febbraio 2005.</p>
<h2>Cosa succede con e senza Ajax</h2>
<p><!--adv300--></p>
<p>Supponiamo di avere una pagina con un form composto da tre campi di testo: nome, cognome e telefono. Lo script lato-server deve ricevere i tre dati, cercarli nel database e stampare l&#8217;indirizzo associato.</p>
<p><strong>Importante.</strong> Generalmente, lo script utilizzato con una chiamata Ajax è diverso da quello utilizzato per l&#8217;esecuzione senza javascript.</p>
<h4>L&#8217;esecuzione standard dello script</h4>
<p><a rel="attachment wp-att-213" href="http://jblog.it/2009/05/02/come-utilizzare-ajax-basi-librerie-framework-ottimizzazione-caching-usabilita_202.html/attachment/1"><img class="size-full wp-image-213 alignnone" title="Esecuzione di uno script senza utilizzare Ajax" src="http://jblog.it/wp-content/uploads/2009/04/1.png" alt="Esecuzione di uno script senza utilizzare Ajax" width="600" height="170" /></a></p>
<p><em>N.B. i rettangoli tratteggiati indicano cosa viene caricato.</em></p>
<p><strong>P</strong><strong>rima fase.</strong> Si carica la pagina html, si scrivono i dati nel form e si inviano al server premendo il pulsante &#8220;invia&#8221;. Oltre a quelle dei dati, il server riceverà le richieste http degli altri componenti della pagina che dovranno essere ricaricati.</p>
<p><strong>Seconda fase.</strong> Il server cerca l&#8217;indirizzo nel database, e il browser <strong>ricarica completamente </strong>la pagina con i nuovi dati o con un messaggio di errore (es. &#8220;indirizzo non trovato&#8221;).</p>
<h4>L&#8217;esecuzione dello script utilizzando Ajax</h4>
<p><a rel="attachment wp-att-218" href="http://jblog.it/2009/05/02/come-utilizzare-ajax-basi-librerie-framework-ottimizzazione-caching-usabilita_202.html/attachment/2"><img class="alignnone size-full wp-image-218" title="Esecuzione di uno script ajax" src="http://jblog.it/wp-content/uploads/2009/04/2.png" alt="Esecuzione di uno script ajax" width="600" height="170" /></a></p>
<p><strong>Prima fase.</strong> Si carica la pagina html, si scrivono i dati nel form e si inviano al server premendo il pulsante &#8220;invia&#8221;. Al server arriva solo una richiesta http: quella dei dati inviati. Inoltre vengono stampati i componenti da mostrare successivamente  (&#8220;tutto ok!&#8221;, &#8220;i dati &#8230; correttamente&#8221;, ecc.) nascondendoli con le regole dei css.</p>
<p><strong>Seconda fase.</strong> Il server cerca l&#8217;indirizzo nel database e, una volta trovato, viene rispedito al browser che aggiornerà il componente riservato all&#8217;indirizzo. Gli altri contenuti stampati precedentemente (&#8220;tutto ok!&#8221;, &#8220;i dati &#8230; correttamente&#8221;, ecc.), vengono resi visibili, mentre i componenti relativi al form vengono nascosti. Per nascondere e mostrare i componenti si utilizzano le regole dei css.</p>
<h2>Framework e librerie javascript</h2>
<p>Un framework javascript è un <strong>insieme di librerie</strong> che facilita la scrittura di codice e applicazioni javascript.</p>
<p><strong>Perché utilizzare un framework?</strong></p>
<ul>
<li>Ti permette di scrivere in <strong>poche righe</strong> quello che in javascript &#8220;puro&#8221; richiderebbe centinaia di righe</li>
<li>Elimina il problema della <strong>compatibilità browser-javascript</strong> eseguendo istruzioni diverse a seconda del browser che si sta utilizzando</li>
</ul>
<p>Ecco i framework più famosi.</p>
<h5>Prototype</h5>
<p><img class="alignright size-full wp-image-227" title="Prototype is a JavaScript Framework that aims to ease development of dynamic web applications" src="http://jblog.it/wp-content/uploads/2009/04/prototype.png" alt="Prototype is a JavaScript Framework that aims to ease development of dynamic web applications" width="139" height="72" />Prototype is a JavaScript Framework that aims to ease development of dynamic web applications.</p>
<p><a href="http://www.prototypejs.org/" target="_blank">http://www.prototypejs.org/</a></p>
<h5>jQuery</h5>
<p><img class="alignright size-full wp-image-230" title="jQuery is a new kind of JavaScript Library." src="http://jblog.it/wp-content/uploads/2009/04/jquery.png" alt="jQuery is a new kind of JavaScript Library." width="226" height="59" />jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript.</p>
<p><a href="http://jquery.com/" target="_blank">http://jquery.com/</a></p>
<h5>MooTools</h5>
<p><img class="alignright size-full wp-image-231" title="MooTools is a compact, modular, Object-Oriented JavaScript framework" src="http://jblog.it/wp-content/uploads/2009/04/mootools.png" alt="MooTools is a compact, modular, Object-Oriented JavaScript framework" width="249" height="74" />MooTools is a compact, modular, Object-Oriented JavaScript framework designed for the intermediate to advanced JavaScript developer. It allows you to write powerful, flexible, and cross-browser code with its elegant, well documented, and coherent API.</p>
<p><a href="http://mootools.net/" target="_blank">http://mootools.net/</a></p>
<h5>Dojo</h5>
<p><img class="alignright size-full wp-image-232" title="Dojo. Solve problems faster. Create better user experiences. Liberally licensed. Everything you need, all in one place." src="http://jblog.it/wp-content/uploads/2009/04/dojo.png" alt="Dojo. Solve problems faster. Create better user experiences. Liberally licensed. Everything you need, all in one place." width="147" height="32" />Solve problems faster. Create better user experiences. Liberally licensed. Everything you need, all in one place.</p>
<p><a href="http://dojotoolkit.org/" target="_blank">http://dojotoolkit.org/</a></p>
<h2>Ajax, jQuery e Php all&#8217;opera</h2>
<p>Generalmente un&#8217;applicazione Ajax è composta dalla pagina html e dallo script lato-server da richiamare successivamente via javascript.</p>
<p>Il framework che utilizzo è <a href="http://jquery.com/" target="_blank">jQuery</a>, soprattutto perché, nel complesso, è molto più leggero e veloce rispetto agli altri.</p>
<p>Analizziamo ora il codice dell&#8217;applicazione Ajax di cui ho parlato prima.</p>
<p><strong>Requisiti.</strong> Php 5.2, MySql 5, jQuery 1.3.</p>
<p><strong>Demo dell&#8217;applicazione. </strong>Puoi provare l&#8217;applicazione Ajax <a href="http://download.jblog.it/ajax_phone/" target="_blank">qui</a>.</p>
<h4>Pagina html e codice javascript</h4>
<p>Questa pagina si può dividere in due parti.</p>
<ul>
<li>codice html</li>
<li>codice javascript per la gestione delle chiamate ajax e del codice html</li>
</ul>
<p>Puoi vedere il file completo <a title="Pagina html e codice javascript" href="http://download.jblog.it/ajax_phone/index.txt" target="_blank">qui</a>.</p>
<h5>Html</h5>
<p>All&#8217;interno del tag &lt;body&gt; si possono distinguere due &lt;div&gt;. Il primo (id=&#8221;form_panel&#8221;) ospita il form e un &lt;h3&gt; per la scrittura degli errori (id=&#8221;errors&#8221;); il secondo (id=&#8221;address_panel&#8221;) ospita un &lt;div&gt; (id=&#8221;the_address&#8221;) in cui si scriverà l&#8217;indirizzo trovato.</p>
<pre lang="html">&lt;body&gt;
	&lt;!-- Area del form --&gt;
	&lt;div id="form_panel"&gt;
		&lt;h1&gt;INSERISCI I DATI&lt;/h1&gt;
		&lt;h3 id="errors" style="display:none;color:#CC0000;"&gt;&lt;/h3&gt;
		&lt;form action=""&gt;
			&lt;p&gt;
				&lt;div&gt;&lt;b&gt;Nome&lt;/b&gt; &lt;small&gt;(solo lettere)&lt;/small&gt;&lt;/div&gt;
				&lt;input id="firstname" name="firstname" type="text" value="" /&gt;
				&lt;small id="firstname_msg" style="color:#CC0000;"&gt;&lt;/small&gt;
			&lt;/p&gt;
			&lt;p&gt;
				&lt;div&gt;&lt;b&gt;Cognome&lt;/b&gt; &lt;small&gt;(solo lettere)&lt;/small&gt;&lt;/div&gt;
				&lt;input id="lastname" name="lastname" type="text" size="30" value="" /&gt;
				&lt;small id="lastname_msg" style="color:#CC0000;"&gt;&lt;/small&gt;
			&lt;/p&gt;
			&lt;p&gt;
				&lt;div&gt;&lt;b&gt;Telefono&lt;/b&gt; &lt;small&gt;(numeri, trattino "-", parentesi "(" e ")", spazio " ")&lt;/small&gt;&lt;/div&gt;
				&lt;input id="phone" name="phone" type="text" value="" /&gt;
				&lt;small id="phone_msg" style="color:#CC0000;"&gt;&lt;/small&gt;
			&lt;/p&gt;
			&lt;p&gt;&lt;input id="send" name="send" type="button" value="Invia" /&gt;&lt;/p&gt;
		&lt;/form&gt;
	&lt;/div&gt;

	&lt;!-- Area dell'indirizzo (trovato) --&gt;
	&lt;div id="address_panel" style="display:none;"&gt;
		&lt;h1&gt;INDIRIZZO&lt;/h1&gt;
		&lt;p id="the_address"&gt;&lt;/p&gt;

		&lt;a href="#" id="back_to_form"&gt;&amp;lt; indietro&lt;/a&gt;
	&lt;/div&gt;
&lt;/body&gt;</pre>
<h5>Javascript</h5>
<p>Il codice javascript viene scritto direttamente nel codice html, ma potrebbe essere scritto in un file esterno (.js).</p>
<p>Vengono specificate 3 funzioni e 3 variabili.</p>
<p><strong>$(document).ready(function(){ &#8230; }).</strong> In realtà, questa non è una funzione, ma un metodo di jQuery che, al posto dei &#8220;&#8230;&#8221;, consente di specificare il codice javascript da eseguire quando la pagina ha completato il caricamento.</p>
<p><strong>function form_check().</strong> Esegue dei controlli sui valori dei campi e restituisce &#8220;true&#8221; se non ci sono errori, altrimenti &#8220;false&#8221;.</p>
<p><strong>function form_ajax_send().</strong> Invia i dati del form allo script &#8220;myscript.php&#8221;, attende e gestisce la risposta.</p>
<p><strong>var form_msgs = new Array(&#8230;).</strong> Array degli errori relativi al form (es. &#8220;dati non corretti&#8221;).</p>
<p><strong>var error_msgs = new Array(&#8230;).</strong> Array degli errori relativi all&#8217;invio e alla risposta dei dati (es. &#8220;errore del db&#8221;).</p>
<p><strong>var regexps = new Array(&#8230;).</strong> Espressioni regolari utilizzate in form_check() per controllare i caratteri dei dati inseriti.</p>
<h5>L&#8217;oggetto XMLHttpRequest</h5>
<p>Per inviare richieste http dinamiche bisogna utilizzare l&#8217;oggetto XMLHttpRequest. Questo oggetto ha una serie di <strong>proprietà </strong>e <strong>metodi</strong>.</p>
<p><strong>Uno dei principali svantaggi</strong> legati all&#8217;utilizzo di questo oggetto sta nel fatto che non è standardizzato, quindi non è riconosciuto universalmente da tutti i browser. Infatti, Internet Explorer 6 e precedenti lo vedono come un ActiveX da richiamare in maniera diversa rispetto ai browser Mozilla.</p>
<p><strong>La soluzione</strong> è quella di utilizzare un framework e lasciare che sia lui a occuparsi di effettuare i controlli di compatibilità e differenziare la chiamata e il funzionamento dell&#8217;oggetto XMLHttpRequest.</p>
<p><strong>Per conoscere meglio l&#8217;oggetto XMLHttpRequest</strong> puoi consultare la <a title="The XMLHttpRequest" href="http://www.w3.org/TR/XMLHttpRequest/" target="_blank">pagina ufficiale del w3c (in inglese)</a> oppure la <a title="XMLHttpRequest" href="http://it.wikipedia.org/wiki/XMLHttpRequest" target="_blank">pagina su Wikipedia</a>.</p>
<p><strong>Per approfondire</strong> la gestione di Ajax con jQuery puoi leggere la pagina della <strong>documentazione ufficiale di jQuery</strong> relativa ad Ajax: <a title="jQuery: Ajax" href="http://docs.jquery.com/Ajax" target="_blank">http://docs.jquery.com/Ajax</a>.</p>
<h5>Ajax</h5>
<p>Analizziamo le righe di codice javascript relative alla gestione della richiesta e della risposta asincrona.</p>
<pre lang="js">$.get("myscript.php",{firstname_get:firstname,lastname_get:lastname,phone_get:phone},
	// funzione "callback", cioé eseguita quando vengono restituiti i dati dallo script "myscript.php"
	function(data,status)
	{
		if(status=="success") { ... }
		else { ... } // status=="failure"
	}
);</pre>
<p><strong>$.get.</strong> Questa funzione effettua una richiesta GET. Alternativamente si poteva utilizzare $.post. A seconda del tipo di richiesta, nell0 script lato server bisogna utilizzare gli array $_GET e $_POST per ottenere i dati inviati.</p>
<p><strong>&#8220;myscript.php&#8221;.</strong> Il primo argomento della funzione $.get. Specifica lo script da utilizzare.</p>
<p><strong>{firstname_get:firstname,lastname_get:lastname,phone_get:phone}.</strong> Il secondo argomento della funzione $.get. Questo è un tipo di dati chiamato &#8220;Map&#8221;, dove &#8220;firstname&#8221;, &#8220;lastname&#8221; e &#8220;phone&#8221; sono le variabili riempite con i valori del form, e &#8220;firstname_get&#8221;, &#8220;lastname_get&#8221; e &#8220;phone_get&#8221; sono i nomi delle variabili passate allo script. Quindi, in myscript.php per leggere il cognome non utilizzeremo $_GET['lastname'] ma $_GET['lastname_get'].</p>
<p><strong>function(data,status).</strong> Il terzo argomento della funzione $.get. Rappresenta la funzione &#8220;callback&#8221;, ovvero la funzione da utilizzare quando si riceve la risposta. Poiché la risposta è asincrona, cioé avviene in un secondo momento rispetto all&#8217;invio dei dati, non possiamo scrivere:</p>
<pre lang="js">if(form_check())
{
	ajax_invia_dati();
	ajax_gestisci_risposta();
}</pre>
<p>poiché, quando verrà chiamata la funzione ajax_gestisci_risposta() sicuramente la risposta non sarà ancora arrivata.</p>
<p>Per questo motivo è necessario specificare la cosiddetta <strong>funzione &#8220;callback&#8221;</strong> che verrà eseguita non appena ajax fornirà una risposta. Questa funzione ha due parametri: <strong>data</strong> (dati ricevuti), <strong>status </strong>(stato della risposta). Se status è &#8220;success&#8221; significa che tutto è andato a buon fine, altrimenti status sarà &#8220;failure&#8221;.</p>
<p><strong>Come ottenere l&#8217;oggetto XMLHttpRequest.</strong> Le funzioni $.get, $.post, ecc. restituiscono l&#8217;oggetto XMLHttpRequest che potrà essere utilizzato con tutti i suoi metodi e le sue proprietà.</p>
<h4>Script lato server (php)</h4>
<ul>
<li>Effettua una connessione al database</li>
<li>Esegue la query con i dati ricevuti</li>
<li>Stampa una stringa fra queste: &#8220;db error&#8221;, &#8220;no data&#8221;, o l&#8217;indirizzo trovato</li>
</ul>
<p>Puoi vedere il file completo <a title="Pagina html e codice javascript" href="http://download.jblog.it/ajax_phone/myscript.txt" target="_blank">qui</a>.</p>
<pre lang="php">&lt;?php

header('Expires:'.date("D, d M Y H:i:s",time()+2600000).' GMT');
header('Cache-Control:public,max-age=2600000');

$mydb = @new mysqli('localhost', 'root', 'root', 'mydb');

if(mysqli_connect_errno()!=0) { echo 'db error'; }
else
{
	// effettua la query
	$result = @$mydb-&gt;query("
	SELECT	`Address`
	FROM	`info`
	WHERE	`Lastname`='".$_GET['lastname_get']."' AND
		`Firstname`='".$_GET['firstname_get']."' AND
		`Phone`='".$_GET['phone_get']."'		;");

	// controlla quanti record sono stati trovati (se 0: indirizzo non trovato)
	if($mydb-&gt;affected_rows==0)	{ echo 'no data'; }

	// indirizzo trovato
	else
	{
		$address = $result-&gt;fetch_array(MYSQLI_NUM);
		echo $address[0];
	}
}
?&gt;</pre>
<h5>Dati restituiti dallo script</h5>
<p><strong> </strong></p>
<ul>
<li>&#8220;db error&#8221;, se si verifica un errore relativo al database (in fase di connessione)</li>
<li>&#8220;no data&#8221;, se non viene trovato l&#8217;indirizzo</li>
<li>stringa dell&#8217;indirizzo, se viene trovato l&#8217;indirizzo</li>
</ul>
<h5>Come impostare lo script per i test</h5>
<p>Se vuoi testare lo script è necessario effettuare alcune semplici operazioni.</p>
<ul>
<li>All&#8217;interno di myscript.php individua la riga $mydb = @new mysqli(&#8216;localhost&#8217;, &#8216;root&#8217;, &#8216;root&#8217;, &#8216;mydb&#8217;); e sostituisci i valori del tuo database: host, username, password, database.</li>
<li>Crea la tabella &#8220;info&#8221; nel tuo database. Nello script c&#8217;è una query (CREATE TABLE &#8230; ) da copiare e far eseguire subito dal tuo dbms (es. phpMyAdmin). Se la crei manualmente è necessario creare 5 campi chiamati ID, Lastname, Firstname, Phone, Address.</li>
<li>Infine, inserisci un paio di record in modo che l&#8217;applicazione Ajax possa trovare qualc0sa nella tabella.</li>
</ul>
<h2>Formati di scambio dati</h2>
<p><img class="alignright size-full wp-image-361" title="Scambio dati" src="http://jblog.it/wp-content/uploads/2009/05/senza-titolo-1.png" alt="Scambio dati" width="342" height="134" />Per i dati da inviare come risposta possono essere utilizzati <strong>vari formati</strong>: testo semplice, html, xml, json, ebml.</p>
<p>Lo script dell&#8217;<strong>esempio precedente</strong> stampa <strong>testo semplice</strong>.</p>
<h4>Testo semplice e html</h4>
<p>Preferibile se si devono sviluppare applicazioni semplici che non richiedono massicci scambi di dati e complesse elaborazioni.</p>
<p>Il maggior vantaggio sta nel fatto che testo semplice e codice html non richiedono ulteriori elaborazioni per rendere i dati rappresentabili all&#8217;interno di una pagina xhtml o html.</p>
<h4>Json</h4>
<p>Json, acronimo di <em>JavaScript Object Notation</em>,  è un ottimo formato per lo scambio dati.</p>
<p>Si possono rappresentare <strong>oggetti </strong>e <strong>array</strong>:</p>
<pre lang="js">var object = { name : "Giacomo", phone: "123456789", object2: { msg: "Ciao" } };
var array = ["mystring", 100, { msg: "Ciao" }, object, 5*2, 0.134];</pre>
<p>Per processare una risposta in formato Json, anziché $.get è necessario utilizzare<strong>$.getJson</strong>. Questa funzion processa automaticamente una risposta in formato Json in modo da poter utilizzare subito i dati.</p>
<p>Ad esempio, se la risposta è:</p>
<pre lang="js">var object = { name : "Giacomo", phone: "123456789", object2: { msg: "Ciao" } };
var array = ["mystring", 100, { msg: "Ciao" }, object, 5*2, 0.134];</pre>
<p>all&#8217;interno della funzione &#8220;callback&#8221; potremmo utilizzare le due variabili scrivendo semplicemente:</p>
<pre lang="js">object.name.length; // per ottenere la lunghezza della stringa "Giacomo"
alert(object.object2.msg); // per stampare un alertbox con il messaggio "Ciao"
newvar = array[4] + 3; // per assegnare alla variabile newvar il valore (5*2)+3, cioé 13</pre>
<p>Per saperne di più vai alla pagina ufficiale di Json: <a title="Json official page" href="http://json.org/" target="_blank">http://json.org/</a>.</p>
<h4>XML</h4>
<p>XML, acronimo di <em>eXtensible Markup Language</em>, è un <strong>metalinguaggio di markup</strong> che permette di definire tag personalizzare per strutturare documenti complessi. Una volta ottenuta una risposta formattata in XML è necessario elaborarla per poterla gestire.</p>
<p>La lettura e l&#8217;elaborazione di un testo XML consiste nello scorrere la struttura del documento per recuperare i dati contenuti nei tag XML. Per scorrere la struttura del documento esistono <strong>librerie javascript</strong> che consentono di farlo semplicemente.</p>
<p>Utilizzare questo formato è vantaggioso nel caso in cui ci siano molti dati da ricevere, mentre è sconsigliabile nel caso in cui ricevano pochi dati in quanto i caratteri per i tag XML potrebbero superare quelli per i dati effettivi.</p>
<h2>Memorizza le risposte Ajax in cache per evitare richieste duplicate</h2>
<p>Come detto prima, le risposte Ajax non sono altro che risposte HTTP e, come in tutte le risposte HTTP, possono essere inviati gli header.</p>
<p>Naturalmente, gli header devono essere inviati dallo script lato server, prima di qualsiasi output.</p>
<p>Per memorizzare le risposte Ajax nella cache si possono utilizzare i campi di intestazione Cache-Control, Expires, Pragma, <strong>ETag</strong>. Nei casi in cui non si possa utilizzare la cache del browser ricorreremo a una tecnica javascript.</p>
<p><strong>Per approfondire la gestione della cache</strong> dai uno sguardo al post precedente: <a title="Ridurre le richieste HTTP (parte 1): come utilizzare la cache del browser" href="http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html">http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html</a>.</p>
<h4>Richieste GET e POST: come si comporta il browser</h4>
<p>Nell&#8217;esempio, utiliziamo un solo script lato server che restituisce 3 output diversi a seconda dell&#8217;esito dell&#8217;operazione: &#8220;db error&#8221; per l&#8217;errore del database, &#8220;no data&#8221; se non è stato trovato l&#8217;indirizzo, e la stringa dell&#8217;indirizzo trovato nel database.</p>
<p>Ti consiglio di leggere questo interessante articolo (in inglese) del w3c: <a title="URIs, Addressability, and the use of HTTP GET and POST" href="http://www.w3.org/2001/tag/doc/whenToUseGet.html" target="_blank">URI, indirizzabilità, e l&#8217;uso di GET e POST</a>.</p>
<p>Il comportamento del browser cambia in base al tipo di richiesta (GET e POST) e agli header inviati dallo script lato server. Analizziamo alcuni casi più da vicino.</p>
<h5>Le richieste GET</h5>
<p><strong> </strong>L&#8217;indirizzo di una richiesta GET ha la forma:</p>
<pre lang="plaintext">http://localhost/ajax_phone/myscript.php?par1=ciao&amp;par2=hello</pre>
<p>Il comportamento di <strong>default </strong>del browser consiste nell&#8217;inviare sempre una nuova richiesta.</p>
<p>Tuttavia, se vogliamo che il browser memorizzi per 1 ora la risposta dello script lato server, inviamo i seguenti header:</p>
<pre lang="plaintext">header('Expires:Sun, 03 May 2009 23:18:45 GMT');
header('Cache-Control:public,max-age=3600');
header('Pragma:public');</pre>
<p>In questo caso, quando l&#8217;applicazione Ajax invia la prima richiesta, il browser legge lo script e lo memorizza in cache. La volta successiva possono verificarsi due casi:</p>
<ul>
<li>se si inviano dei <strong>dati diversi</strong> (ad es., se invece di &#8220;par2=hello&#8221; inviamo &#8220;par2=welcome&#8221;) il browser effettua una nuova richiesta e la memorizza in cache</li>
<li>se si inviano gli <strong>stessi dati</strong>, il browser si accorge che l&#8217;indirizzo della richiesta è uguale, quindi legge i dati dalla cache evitando di effettuare una nuova richiesta</li>
</ul>
<p><strong>Differenziare gli header.</strong> Se alcune richieste non devono essere memorizzate in cache, puoi inviare degli header diversi a seconda dell&#8217;ouput generato dallo script (prima di stampare qualsiasi output). Ad esempio:</p>
<pre lang="php">if($output!="error")
{
	header('Expires:Sun, 03 May 2009 23:18:45 GMT');
	header('Cache-Control:public,max-age=3600');
	header('Pragma:public');
}
else
{
	header('Expires:Sun, 01 Jan 1970 02:00:00 GMT');
	header('Cache-Control:no-cache');
	header('Pragma:no-cache');
}</pre>
<p><strong>Forzare la richiesta.</strong> Per fare in modo che il browser effettui una nuova richiesta, anche se questa è già presente nella cache, basta inviare un ulteriore parametro con un valore variabile, ad esempio un numero casuale.</p>
<pre lang="js">$.get("myscript.php",{firstname_get:firstname,lastname_get:lastname,phone_get:phone,random:Math.random()},
	function(data,status){...});</pre>
<h5>Le richieste POST</h5>
<p>L&#8217;indirizzo di una richiesta POST ha la forma:</p>
<pre lang="plaintext">http://localhost/ajax_phone/myscript.php</pre>
<p><strong>E i parametri?</strong> Vengono inviati tramite protocollo HTTP, ma non sono visibili al browser.</p>
<p><strong>Le richieste POST non possono essere memorizzate in cache.</strong></p>
<h5>Come evitare le richieste duplicate</h5>
<p>Abbiamo visto che le richieste POST non possono essere memorizzate in cache.</p>
<p>Tuttavia è possibile evitare le richieste duplicate grazie a qualche riga di javascript.</p>
<p>Questa tecnica consiste nel <strong>memorizzare i dati inviati e ricevuti in un array</strong>, in modo che, prima di inviare una richiesta, si controlla se i dati da inviare sono già presenti nell&#8217;array. Se sono presenti, si leggono i dati ricevuti in corrispondenza dei dati richiesti e si procede con l&#8217;esecuzione dell&#8217;applicazione.</p>
<pre lang="js">var my_array() = new Array();

/* Una volta riempito l'array avrà questo aspetto
myarray = Array(
	Array( Array('Mario','Rossi',3429752370), 'no data' ),
	Array( Array('Giacomo','Ratta',4325233), 'Via Beethoven, 21' ),
);
*/</pre>
<p>Ogni elemento dell&#8217;array è un array di due elementi. Il primo è l&#8217;array dei dati inviati; il secondo è la stringa dell&#8217;output restituito.</p>
<pre lang="js">// Esegue le operazioni con i dati ricevuti
function esegui_le_operazioni(data) { ... }

if(form_check())
{
	// Leggo i valori dei 3 campi del form
	firstname = $('#firstname').val();
	lastname = $('#lastname').val();
	phone = $('#phone').val();

	// Indica se sono state trovate i dati da inviare
	// Contiene l'indice dell'elemento contenente dati inviati e dati ricevuti
	found = -1;

	// Cerco i dati nell'array
	for(i=0;i&lt;my_array.length;i++)
	{
		// (riga da adattare in base alle proprie esigenze)
		if(my_array[i][0][0]==firstname &amp;&amp; my_array[i][0][1]==lastname &amp;&amp; my_array[i][0][1]==phone)
		{ found=i; break; }
	}

	// I dati sono stati trovati
	if(found&gt;=0)
	{
		esegui_le_operazioni(my_array[found][1]);
	}

	// Dati non trovati: nuova richiesta
	else {
		$.get("myscript.php",{firstname_get:firstname,lastname_get:lastname,phone_get:phone},
		// funzione "callback", cioé eseguita quando vengono restituiti i dati dallo script "myscript.php"
		function(data,status)
		{
			if(status=="success")
			{
				// Inserisco dati inviati e dati ricevuti nell'array
				// riga da adattare in base alle proprie esigenze)
				my_array.push(new Array(new Array(firstname,lastname,phone), data));

				esegui_le_operazioni(data);
			}
			else { ... } // status=="failure"

		}); //end-callback

	} //end-if
}</pre>
<h5>Quando utilizzare GET e quando POST<strong><br />
</strong></h5>
<ul>
<li>Il metodo GET è da preferire quando si devono inviare dati per il normale funzionamento della pagina e degli script</li>
<li>Il metodo POST si deve utilizzare quando quelli da scambiare sono dei dati sensibili (username, password, telefono)</li>
</ul>
<h2>Migliorare l&#8217;usabilità e l&#8217;accessibilità delle applicazioni Ajax</h2>
<p>Spesso nella progettazione delle applicazioni Ajax l&#8217;usabilità lascia un po&#8217; a desiderare: nessun messaggio di successo/errore, caricamenti infiniti senza segni di vita, ecc.</p>
<p>Certo, l&#8217;usabilità è un tema complesso e progettare siti e applicazioni usabili richiede tempo e buone competenze.</p>
<p>Tuttavia, ci sono alcune cose che devono essere fatte e che, fortunatamente, non richiedono troppo tempo.</p>
<p><strong><em>Potrai vedere queste modifiche nello script di esempio.</em></strong></p>
<h4>Errori e messaggi</h4>
<ul>
<li>Ogni campo di input deve avere la relativa area dedicata ai messaggi di errore (&#8220;dati obbligatori&#8221;, &#8220;caratteri non validi&#8221;, ecc.)</li>
<li>La pagina deve avere un&#8217;area destinata ad ospitare i messaggi relativi all&#8217;esecuzione dello script (&#8220;ricerca eseguita con successo&#8221;, &#8220;errore dell&#8217;applicazione&#8221;, &#8220;errore del database&#8221;, ecc.)</li>
</ul>
<h4>Barra di caricamento</h4>
<p><img class="alignright size-full wp-image-360" title="loader" src="http://jblog.it/wp-content/uploads/2009/05/loader.png" alt="loader Come utilizzare Ajax: librerie, framework, ottimizzazione, caching, usabilità" width="220" height="19" />Nella maggior parte della applicazioni, per motivi tecnici, non è possibile inserire una barra di caricamento che rilevi la percentuale reale dei dati caricati fino a quel momento.</p>
<p>Generalmente, si preferisce mostrare un&#8217;immagine gif che può essere una barra di caricamento o un&#8217;animazione generica in modo che faccia sapere all&#8217;utente che l&#8217;applicazione sta lavorando.</p>
<p><strong>Svantaggio.</strong> Durante il caricamento dei dati si potrebbe verificare un malfunzionamento che non blocca la richiesta. In questo caso il caricamento sarebbe infinito provocando l&#8217;abbandono del sito da parte dell&#8217;utente.</p>
<p><strong>Soluzione 1.</strong> Puoi inserire un pulsante da far premere all&#8217;utente per fermare la richiesta http.</p>
<pre lang="html">&lt;button type="button" onclick="stopAjaxRequest();"&gt;Stop&lt;/button&gt;</pre>
<p><strong>Soluzione 2.</strong> Analizza il tuo script e prevedi un tempo massimo entro cui restituire l&#8217;output, e, con javascript, impostare un timer che faccia fermare la richiesta Ajax una volta trascorso il tempo previsto.</p>
<pre lang="js">// esegue la funzione stopAjaxRequest() dopo 10 secondi
setTimeout(stopAjaxRequest(),10000);</pre>
<h5>Come creare la funzione stopAjaxRequest().</h5>
<ul>
<li>L&#8217;oggetto <span>XMLHttpRequest ha il metodo <strong>abort() </strong>che permette di fermare una richiesta http.</span></li>
<li>Le funzioni $.ajax, $.get, $.post, $.getScript, $.getJSON di jquery restituiscono un oggetto <span>XMLHttpRequest.</span></li>
</ul>
<p><strong>1. Creiamo una variabile globale per l&#8217;oggetto <span>XMLHttpRequest, che chiamiamo XHR</span></strong></p>
<pre lang="js"><span>var XHR;<strong>
</strong></span></pre>
<p><strong><span>2. Creiamo la funzione</span> stopAjaxRequest() che richiama XHR ed esegue il metodo abort()</strong></p>
<pre lang="js">function stopAjaxRequest() { XHR.abort(); }</pre>
<p><strong><span>3. Assegnamo a XHR l&#8217;oggetto restituito dalla funzione $.get che utilizziamo per inviare i dati</span></strong></p>
<pre lang="js"><span>XHR = $.get("myscript.php",{firstname_get:firstname,lastname_get:lastname,phone_get:phone},
	function(data,status)</span><span> { ... }</span><span>);
</span></pre>
<h4>Se javascript è disabilitato&#8230;</h4>
<p>Purtroppo, ancora oggi ci sono utenti che utilizzano browser che non eseguono codice javascript, che hanno scarsa compatibilità oppure con javascript disattivato.</p>
<p>La <strong>soluzione </strong>è quella di progettare applicazioni che funzionino sia con javascript che senza.</p>
<p>Questo potrebbe andare bene per la piccola applicazione Ajax realizzata per questo post. Tuttavia, se le applicazioni sono di un certo livello, il carico di lavoro aumenta notevolmente. Quindi progettare applicazioni ibride ha senso solo quando le applicazioni da realizzare <strong><span style="text-decoration: underline;">devono</span> </strong>offrire il <strong>massimo della compatibilità</strong> con i browser usati dagli utenti (ad es. siti governativi, pubblica amministrazione, ecc.)</p>
<p><strong>Secondo me</strong>, data la piccola percentuale di browser non compatibili e di utenti che disattivano (erroneamente) javascript, e la presenza di siti importanti come ebay, microsoft, youtube che non offrono l&#8217;alternativa &#8220;no javascript&#8221;, si può benissimo sviluppare un sito senza preoccuparsi degli utenti che non potranno eseguire javascript.</p>
<p>Nel <strong>tag &lt;noscript&gt;</strong> è possibile inserire il codice html da eseguire in caso di &#8220;javascript disabilitato&#8221;.</p>
<p>Alcune volte l&#8217;ho utilizzato per nascondere dei componenti che avevano senso solo con javascript disabilitato. Lo so&#8230; sintatticamente non è corretto, però potrebbe esserti utile.</p>
<p>Supponiamo di avere un link che fa apparire un alert:</p>
<pre lang="js">&lt;a id="alert_click" href="#" onclick="javascript:alert('Ciao!');"&gt;Clicca qui&lt;/a&gt;</pre>
<p>Per nasconderlo, in caso di javascript disabilitato, scriviamo:</p>
<pre lang="html">&lt;noscript&gt;
&lt;style type="text/css"&gt;
#alert_click { display:none; }
&lt;/style&gt;
&lt;/noscript&gt;</pre>
<h2>Svantaggi di Ajax</h2>
<ul>
<li>Le chiamate effettuate non vengono registrate nella cronologia, a differenza di quanto avviene utilizzando iframe nascosti</li>
<li>I pulsanti &#8220;avanti&#8221; e &#8220;dietro&#8221; non sono utilizzabili poiché le chiamate Ajax non vengono memorizzate nella cronologia</li>
<li>L&#8217;utilizzo esclusivo di javascript viola il requisito 15 della legge Stanca: &#8220;la pagina deve essere fruibile anche in assenza di script&#8221;</li>
<li>L&#8217;oggetto XMLHttpRequest non è compatibile con tutti i browser. Internet Explorer 6 e precedenti lo vedono come oggetto ActiveX, e il browser potrebbe essere impostato a un livello di sicurezza tale da non permettere l&#8217;esecuzione di controlli ActiveX</li>
<li>L&#8217;oggetto XMLHttpRequest può comunicare solo all&#8217;interno del dominio. Se la destinazione è esterna al dominio bisogna creare un proxy lato server per poter comunicare all&#8217;esterno.</li>
<li>Poiché i motori di ricerca non eseguono codice javascript, essi non possono indicizzare i contenuti generati dinamicamente con javascript e Ajax</li>
</ul>
<h2>Libri e risorse utili</h2>
<h5>Ajax. Guida per lo sviluppatore. Seconda edizione. Hoepli (2007).</h5>
<p><img class="alignright size-full wp-image-351" title="Ajax. Guida per lo sviluppatore. Seconda edizione" src="http://jblog.it/wp-content/uploads/2009/05/4960-300x300.jpg" alt="Ajax. Guida per lo sviluppatore. Seconda edizione" width="71" height="100" />Con Ajax guida per lo sviluppatore scoprirete come sfidare le regole tradizionali di quello che può accadere sul Web e come liberarvi del consueto approccio “click and wait”, approfondendo le tecniche, i pattern e i casi di utilizzo di Ajax, così da crearvi un’esperienza d’uso senza precedenti nelle vostre applicazioni.</p>
<p>Link: <a title="Ajax. Guida per lo sviluppatore. Seconda edizione" href="http://www.hoepli.it/editore/visbook.asp?id=978-88-203-3923-4" target="_blank">http://www.hoepli.it/editore/visbook.asp?id=978-88-203-3923-4</a>.</p>
<h5>Ajax e Php. Sviluppare applicazioni web dinamiche. Hoepli (2007)</h5>
<p><img class="alignright size-full wp-image-352" title="Ajax e Php. Sviluppare applicazioni web dinamiche" src="http://jblog.it/wp-content/uploads/2009/05/copj13.jpg" alt="Ajax e Php. Sviluppare applicazioni web dinamiche" width="70" height="100" /><span class="tcorpotesto">AJAX e PHP. Sviluppare applicazioni web dinamiche è la risorsa più pratica ed efficiente che possiate utilizzare per entrare nell&#8217;entusiasmante mondo di AJAX. Questo libro vi spiegherà infatti come creare applicazioni web in PHP che sfruttino al massimo le tecnologie Ajax.<br />
</span></p>
<p>Link: <a title="Ajax e Php. Sviluppare applicazioni web dinamiche" href="http://www.hoepli.it/libro/ajax-php.asp?ib=9788820339432&amp;pc=000022007002012" target="_blank">http://www.hoepli.it/libro/ajax-php.asp</a></p>
<h5>Siti e pagine</h5>
<p><a title="Ajax: A New Approach to Web Applications" href="http://www.adaptivepath.com/ideas/essays/archives/000385.php" target="_blank">Ajax: A New Approach to Web Applications</a></p>
<p><a title="The XMLHttpRequest Object" href="http://www.w3.org/TR/XMLHttpRequest/" target="_blank">W3C: The XMLHttpRequest Object</a></p>
<p><a title="Wikipedia: l'oggetto XMLHttpRequest" href="http://it.wikipedia.org/wiki/XMLHttpRequest" target="_blank">Wikipedia: l&#8217;oggetto XMLHttpRequest</a></p>
<p><a title="jQuery: Ajax" href="http://docs.jquery.com/Ajax" target="_blank">jQuery: Ajax</a></p>
<p><a title="Json official page" href="http://json.org/" target="_blank">JSON.org</a></p>
<p><a title="Ridurre le richieste HTTP (parte 1): come utilizzare la cache del browser" href="http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html">Ridurre le richieste HTTP (parte 1): come utilizzare la cache del browser</a></p>
<p><a title="URIs, Addressability, and the use of HTTP GET and POST" href="http://www.w3.org/2001/tag/doc/whenToUseGet.html" target="_blank">W3C: URIs, Addressability, and the use of HTTP GET and POST</a></p>
<img src="http://jblog.it/?ak_action=api_record_view&id=202&type=feed" alt=" Come utilizzare Ajax: librerie, framework, ottimizzazione, caching, usabilità"  title="Come utilizzare Ajax: librerie, framework, ottimizzazione, caching, usabilità" />]]></content:encoded>
			<wfw:commentRss>http://jblog.it/2009/05/02/come-utilizzare-ajax-basi-librerie-framework-ottimizzazione-caching-usabilita_202.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ridurre le richieste HTTP (parte 1): come utilizzare la cache del browser</title>
		<link>http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html</link>
		<comments>http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html#comments</comments>
		<pubDate>Fri, 24 Apr 2009 20:56:12 +0000</pubDate>
		<dc:creator>Giacomo</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Ottimizzazione]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[meta]]></category>
		<category><![CDATA[mod_expires]]></category>
		<category><![CDATA[mod_headers]]></category>
		<category><![CDATA[ottimizzare]]></category>
		<category><![CDATA[richieste http]]></category>

		<guid isPermaLink="false">http://jblog.it/?p=124</guid>
		<description><![CDATA[Iniziamo una lunga serie di articoli sull&#8217;ottimizzazione dei siti web in cui verranno trattate le tecniche e i suggerimenti per rendere efficiente il proprio sito web.
In questo articolo parlo della cache dei browser, come e perché gestirla. Vedrai cos&#8217;è una richiesta http, un&#8217;intestazione http e le tre tecniche principali per istruire il browser su come dovrà [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html"><img class="alignright size-full wp-image-184" title="Green Archive" src="http://jblog.it/wp-content/uploads/2009/04/greenarchive.jpg" alt="Green Archive" width="270" height="180" /></a>Iniziamo una <strong>lunga serie di articoli sull&#8217;ottimizzazione dei siti web</strong> in cui verranno trattate le tecniche e i suggerimenti per rendere efficiente il proprio sito web.</p>
<p><span class="highlight_yellow"><strong>In questo articolo</strong> parlo della cache dei browser, come e perché gestirla. Vedrai cos&#8217;è una richiesta http, un&#8217;intestazione http e le tre tecniche principali per istruire il browser su come dovrà comportarsi con gli elementi di una pagina, cioé, quando leggerli dal server d&#8217;origine e quando caricarli dalla cache.</span><br />
<span id="more-124"></span></p>
<h2>Cos&#8217;è una richiesta http?</h2>
<p><!--adv300--></p>
<p>Quando il browser visita un sito apre una connessione con l&#8217;host (il server che ospita il sito), composta da una <strong>richiesta </strong>e da una <strong>risposta</strong>. Supponiamo di voler visitare la pagina http://jblog.it/informazioni.html.</p>
<h5>La richiesta http che invia il browser</h5>
<p><code><strong>GET /informazioni HTTP/1.1</strong><br />
<strong>Host:</strong> jblog.it<br />
<strong>User-Agent:</strong> Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8<br />
<strong>Accept:</strong> text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8<br />
<strong>Accept-Language:</strong> it<br />
<strong>Accept-Encoding:</strong> gzip,deflate<br />
<strong>Accept-Charset:</strong> ISO-8859-1,utf-8;q=0.7,*;q=0.7<br />
<strong>Keep-Alive: </strong>300<br />
<strong>Connection:</strong> keep-alive</code></p>
<h5>La risposta http</h5>
<p><code><strong>HTTP/1.1 200 OK</strong><br />
<strong>Date:</strong> Fri, 24 Apr 2009 10:26:08 GMT<br />
<strong>Server</strong>: Apache<br />
<strong>Keep-Alive:</strong> timeout=15, max=100<br />
<strong>Connection:</strong> Keep-Alive<br />
<strong>Transfer-Encoding:</strong> chunked<br />
<strong>Content-Type:</strong> text/html; charset=UTF-8</code></p>
<p>Le informazioni inviate e restituite potrebbero essere molte di più, ognuna ha un suo preciso significato, e possono essere controllate e gestite via codice (lato client e lato server). Sul sito del w3c puoi trovare l&#8217;elenco completo dei campi di intestazione delle connessioni http: <a rel="nofollow" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html</a>.</p>
<h5>La prima riga della richiesta: GET /informazioni HTTP/1.1</h5>
<p><strong> </strong>In questa riga si trovano sostanzialmente tre informazioni: il <strong>tipo della richiesta</strong> (GET, POST, HEAD, PUT, DELETE, OPTIONS, TRACE), l&#8217;<strong>indirizzo della risorsa</strong> (/informazioni) e il <strong>protocollo </strong>con cui si effettua la richiesta (HTTP/1.1).</p>
<h5>La prima riga della risposta: HTTP/1.1 200 OK</h5>
<p><strong> </strong>Il codice 200 indica il successo della risposta http. Esistono vari codici numerici per indicare l&#8217;esito della risposta http. Ad esempio, il classico <strong>codice 404</strong> indica che non è stata trovata la risorsa specificata nella richiesta http. Se ti interessa puoi trovare una <strong>lista completa</strong> su wikipedia: <a rel="nofollow" href="http://it.wikipedia.org/wiki/Elenco_dei_codici_di_stato_HTTP">http://it.wikipedia.org/wiki/Elenco_dei_codici_di_stato_HTTP</a>.</p>
<h3>Perché bisogna ridurre le richieste http?</h3>
<p>Il numero di richieste http dipende dal <strong>numero di elementi da caricare</strong>. Ad esempio, se in una pagina ci sono 2 immagini e 1 foglio di stile il browser effettuerà 4 richieste http (una è per il codice html della pagina).</p>
<p>Come avrai ben capito, la regola è &#8220;ridurre gli elementi della pagina&#8221;, o meglio &#8220;ottimizzare gli elementi di una pagina senza eliminarne nessuno&#8221;. Con &#8220;ottimizzare&#8221; non intendo &#8220;ridurre la loro dimensione&#8221;. Infatti riducendo la dimensione degli elementi avresti un miglior tempo di caricamento mantenendo lo stesso numero di richieste http.</p>
<h4>Ottimizzare o ridurre?</h4>
<p>Senza dubbio è importantissimo ottimizzare la qualità e le dimensioni dei componenti di una pagina, ma una singola richiesta http è molto più gravosa di qualche kbyte in più. Ecco perché <strong>ridurre le richieste http è fondamentale</strong>.</p>
<h2>I campi di intestazione del protocollo HTTP per gestire la cache</h2>
<p><span style="text-decoration: underline;"><a href="http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html"><img class="alignright size-full wp-image-185" title="Gift Tag" src="http://jblog.it/wp-content/uploads/2009/04/gifttag.jpg" alt="Gift Tag" width="267" height="200" /></a></span>Il protocollo HTTP 1.1 ha alcuni campi di intestazione (o header fields) che consentono di fornire alcune informazioni riguardo un file (data, ultima modifica, periodo, ecc.) e controllare la cache.</p>
<h4>Cache-Control</h4>
<p>Specifica le direttive che devono rispettare tutti i metodi di caching dei componenti restituiti. Le direttive di cache-control:</p>
<ol>
<li>sovrascrivono gli algoritmi di caching di default</li>
<li>non possono essere specificate per una singola cache (se si utilizza un proxy o un gateway)</li>
<li>sono unidirezionali, cioè non implicano che la risposta abbia le stesse direttive</li>
</ol>
<p>Alcune direttive possono essere utilizzate solo in fase di richiesta o solo in fase di risposta.</p>
<ul>
<li><strong>direttive di richiesta: </strong>no-cache, no-store, max-age, max-stale, min-fresh, no-transform, only-if-cached, cache-extension.</li>
<li><strong>direttive di risposta:</strong> public, private, no-cache, no-store, no-transform, must-revalidate, proxy-revalidate, max-age, s-maxage, cache-extension.</li>
</ul>
<p><strong>public.</strong> La risposta può essere memorizzata in qualsiasi cache. Utile se si utilizza una cache condivisa.</p>
<p><strong>private.</strong> La risposta non deve essere memorizzata nella cache condivisa.</p>
<p><strong>no-cache.</strong> Evita che la risposta venga memorizzata in cache. SOLO in fase di risposta è possibile scrivere <code>no-cache="field-name"</code>, dove <em>field-nam</em><em>e</em> è il nome di un campo di intestazione che non si vuole memorizzare in cache. In pratica, quando una risposta (ad es. una pagina) viene memorizzata in cache, vengono memorizzati anche i suoi campi di intestazione. Se uno di quei campi è &#8220;Set-Cookie&#8221; e non vogliamo che venga memorizzato in cache basterà scrivere <code>no-cache="Set-Cookie"</code>. In tal modo la pagina verrà comunque memorizzata in cache senza il campo di intestazione &#8220;Set-Cookie&#8221;. <strong>L&#8217;utilità?</strong> Dato che &#8220;Set-Cookie&#8221; crea un cookie, memorizzandolo con la pagina, quando si riutilizzerà la versione in cache verrà creato nuovamente il cookie.</p>
<p><strong>no-store.</strong> Evita che la risposta venga memorizzata permanentemente nella memoria non-volatile. Questa direttiva si applica a qualsiasi tipo di cache (condivisa e non). La sua utilità consiste nel fatto che si impedisce la memorizzazione di vecchie versioni di pagine e documenti che vengono costantemente aggiornati.</p>
<p><strong>s-maxage. </strong>Specifica il periodo (in secondi) dopo il quale devono essere aggiornate le risposte nella <strong>cache condivisa.</strong> Questa direttiva sovrascrive la direttiva <em>max-age </em>e il campo di intestazione <em>expires</em>.</p>
<p><strong>max-age.</strong> Indica che il client è disposto ad accettare una risposta con un periodo (in secondi) maggiore di quello specificato. Se non è specificata la direttiva <em>max-stale</em>, il client non accetterà una risposta datata.</p>
<p><strong>min-fresh.</strong> Indica che il client è disposto ad accettare una risposta che sia aggiornata <em>almeno</em> a un dato periodo (in secondi).</p>
<p><strong>max-stale.</strong> Indica che il client è disposto ad accettare una risposta che supera la sua scadenza di un certo numero di secondi.</p>
<p><strong>only-if-cached.</strong> Consente di caricare un contenuto solo se in cache è presente una sua versione, altrimenti non viene restituita alcuna risposta. Questa direttiva è utile nelle reti particolarmente lente.</p>
<p><strong>must-revalidate. </strong>Poichè una cache può essere configurata in modo che ignori il tempo di scadenza di una risposta, questa direttiva consente di forzare l&#8217;aggiornamento di una risposta già memorizzata in cache. Questa direttiva viene sempre rispettata dal browser.</p>
<p><strong>proxy-revalidate.</strong> Ha gli stessi effetti di must-revalidate, ma solo sulla cache condivisa.</p>
<p><strong>no-transform.</strong> Evita che una cache intermedia (ad es. di un proxy) manipoli la risposta per risparmiare risorse. Infatti può succedere che un proxy comprima un&#8217;immagine per risparmiare spazio. Questa direttiva è utile nel caso di immagini da trasmettere fedelmente (ad es. in campo medico) in cui ogni pixel deve rimanere al suo posto.</p>
<h4>Expires</h4>
<p>Indica una data (con l&#8217;ora) a partire dalla quale la risposta memorizzata in cache deve essere considerata &#8220;vecchia&#8221;, quindi essere aggiornata.</p>
<p>La data deve essere espressa in un preciso formato definito dal protocollo HTTP. Ad esempio: <code>Tue, 03 Nov 2007 17:30:00 GMT.</code></p>
<p><code>Expires: Tue, 03 Nov 2007 17:30:00 GMT</code></p>
<h4>Pragma</h4>
<p>Indica che la risposta non deve essere memorizzata in cache. L&#8217;unica direttiva è appunto &#8220;no-cache&#8221;.</p>
<p>In pratica esegue la stessa funzione di cache-control=&#8221;no-cache&#8221;, ma è necessario utilizzarla per mantenere la compatibilità con la versione 1.0 del protocollo HTTP.</p>
<p><code>Pragma: no-cache</code></p>
<h4>ETag</h4>
<p>Gli ETag o <strong>Entity Tag</strong> rappresentano un modo semplice ed efficiente per determinare se la risposta nella cache corrisponde a quella che si trova nel server di origine. Concretamente un ETag non è altro che una <strong>stringa che identifica univocamente una risposta memorizzata in cache</strong>.</p>
<p><strong>Com&#8217;è composta la stringa?</strong> Non ha dei valori predefiniti ma deve essere creata in base a dei valori che potrebbero identificare la versione di una risposta. Generalmente si preferisce identificare le risposte in base alla data dell&#8217;ultima modifica e alla dimensione. Queste due informazioni vengono compresse in modo da formare un&#8217;unica stringa di dimensioni contenute, ad esempio utilizzando algoritmi di hashing come md5.</p>
<p><strong>Gli svantaggi.</strong> L&#8217;unico svantaggio è che il formato e il valore di un ETag cambia da server a server. Se un determinato file risiede su più server nella stessa directory, con identiche dimensioni, permessi, timestamp, a seconda del server da cui si legge. La <strong>soluzione </strong>consiste nel creare il valore dell&#8217;ETag con un semplice script lato-server. In pratica, per <strong>avere dei benefici</strong> dagli ETag è necessario gestirli completamente con degli script lato-server, altrimenti è meglio non utilizzarli. <a href="#script1">Ecco un esempio di script</a>.</p>
<p><code>ETag: "0401g4ff812fgk12gqg2g4j7"</code></p>
<h4>Last-Modified</h4>
<p>Rappresenta la data e l&#8217;ora dell&#8217;ultima modifica del file sul server d&#8217;origine nella forma, ad esempio, <code>Tue, 03 Nov 2007 17:30:00 GMT.</code></p>
<p>Questo campo di intestazione è utile soprattutto nelle pagine dinamiche in cui vengono stampati dei dati ricavati da un database, o nei file creati dinamicamente (ad es. un foglio di stile che ne unisce 5 per evitare di avere 5 richieste http).</p>
<h4>If-Match</h4>
<p>Fornisce un metodo efficiente per controllare se la risposta ottenuta corrisponde a quella memorizzata in cache, utilizzando gli <strong>ETag</strong>, ed eventualmente aggiornarla. Viene anche usata per evitare <strong>modifiche accidentali</strong> sull&#8217;errata versione di una risorsa.</p>
<p><code>If-Match:*</code> oppure <code>If-Match:0401g4ff812fgk12gqg2g4j7</code></p>
<p>Nel primo caso, il carattere &#8220;*&#8221; è un carattere speciale e il campo fa corrispondere tutti i componenti di una risposta.</p>
<p>Nel secondo caso, il campo di intestazione fa corrispondere l&#8217;ETag con la stringa specificata.</p>
<h4>If-None-Match</h4>
<p>Fornisce un metodo efficiente per controllare se la risposta ottenuta corrisponde a quella memorizzata in cache, utilizzando gli <strong>ETag</strong>, ed eventualmente aggiornarla.</p>
<p>Al contrario di If-Match non si deve avere la corrispondenza con l&#8217;ETag confrontato o con il carattere &#8220;*&#8221;.</p>
<p><code>If-None-Match:*</code> oppure <code>If-Match:0401g4ff812fgk12gqg2g4j7</code></p>
<h4>If-Modified-Since</h4>
<p>Fornisce un metodo automatico per aggiornare la versione in cache di una risposta che non è stata modificata da una certa data (e ora) nel formato: <code>Tue, 03 Nov 2007 17:30:00 GMT. Se la risposta è stata modificata a partire dalla data specificata si effettua l'aggiornamento della versione in cache, altrimenti viene restituita la versione memorizzata in cache.</code></p>
<p><code>If-Modified-Since: Sat, 12 Oct 2008 20:12:00 GMT</code></p>
<h4>If-Unmodified-Since</h4>
<p>Fornisce un metodo automatico per aggiornare la versione in cache di una risposta che non è stata modificata da una certa data (e ora) nel formato: <code>Tue, 03 Nov 2007 17:30:00 GMT. Se la risposta NON è stata modificata a partire dalla data specificata si effettua l'aggiornamento della versione in cache, altrimenti viene restituita la versione memorizzata in cache.</code></p>
<p><code>If-Unmodified-Since: Sat, 12 Oct 2008 20:12:00 GMT</code></p>
<h4>If-Range</h4>
<p>Se la versione in cache di una risposta è parziale, questo campo di intestazione permette di ottenere solo la parte mancante. La condizione fallisce se la risorsa richiesta è stata modificata. In questo caso sarà effettuata una seconda richiesta per ottenere una risposta completa che aggiorni la versione memorizzata in cache.</p>
<p><code>If-Range: Sat, 12 Oct 2008 20:12:00 GMT</code></p>
<p><code>If-Range: 0401g4ff812fgk12gqg2g4j7</code></p>
<p>Nel primo caso si confronta la data dell&#8217;<strong>ultima modifica</strong>, mentre nel secondo caso si confronta la stringa dell&#8217;<strong>ETag</strong>.</p>
<h2>Come utilizzare i campi di intestazione</h2>
<p><span style="text-decoration: underline;"><a href="http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html"><img class="alignright size-full wp-image-186" title="Thinking" src="http://jblog.it/wp-content/uploads/2009/04/thinking.jpg" alt="Thinking" width="267" height="171" /></a></span>In questo paragrafo non troverai una ricetta pronta per gestire la cache perché non so quali sono le tue esigenze. Leggi attentamente il paragrafo precedente per decidere le operazioni da effettuare in ogni pagina e risorsa del tuo sito.</p>
<p><strong>Il mio consiglio</strong> è quello di analizzare i contenuti delle tue pagine (attuali e futuri) e decidere se memorizzare in cache una particolare risorsa, come gestire la versione della cache, il tempo di validità, ecc.</p>
<p>Se nel paragrafo precedente alcuni punti sono spiegati male, manca qualcosa o ci sono errori  fammelo sapere e correggerò tutto al più presto.</p>
<p>Ci sono <strong>tre metodi</strong> per impostare i campi di intestazione:</p>
<ol>
<li>impostando il tag &lt;meta&gt;</li>
<li>all&#8217;interno del proprio codice lato-server (php, asp, cgi, ecc.)</li>
<li>configurando il web server Apache tramite il file .htaccess o il file principale httpd.conf</li>
</ol>
<h3>1. Impostare i tag &lt;meta&gt;</h3>
<p>Sicuramente conoscerai già il tag &lt;meta&gt;. Probabilmente l&#8217;avrai utilizzato per inserire <strong>description</strong> e <strong>keywords</strong> nelle tue pagine web, per migliorare l&#8217;indicizzazione del tuo sito da parte dei motori di ricerca.</p>
<p>Per ogni campo di intestazione che decidi di utilizzare devi:</p>
<ul>
<li>creare un tag &lt;meta&gt; con gli attributi &#8220;http-equiv&#8221; e &#8220;content&#8221;</li>
<li>scrivere il nome del campo nell&#8217;attributo &#8221;http-equiv&#8221;, rispettando le lettere maiuscole e minuscole</li>
<li>scrivere il valore del campo nell&#8217;attributo &#8220;content&#8221;</li>
</ul>
<h5>Esempi</h5>
<p><code>&lt;meta http-equiv="Cache-Control" content="no-cache" /&gt;<br />
&lt;meta http-equiv="Pragma" content="no-cache" /&gt;<br />
&lt;meta http-equiv="Expires" content="Tue, 03 Nov 2007 17:30:00 GMT" /&gt;</code></p>
<h3>2. Il codice lato-server</h3>
<p>Ogni linguaggio di programmazione ha la sua funzione per inviare un campo di intestazione.</p>
<p>Al momento l&#8217;unico linguaggio che conosco è PHP, con cui basterà scrivere <code>header("Cache-Control: no-cache");</code> .</p>
<p>I campi di intestazione vanno scritti prima di qualsiasi output sulla pagina, altrimenti si verifica un errore che in sostanza dice &#8220;impossibile modificare l&#8217;intestazione &#8211; gli header sono stati già inviati&#8221;.</p>
<p><strong>Tutto qui?</strong> <span style="font-weight: normal;">In teoria non ci sarebbe altro&#8230; Posso solo aggiungere delle situazioni in cui diventa fondamentale utilizzare la funzione <em>header</em>.</span></p>
<h5>Combinare più fogli di stile</h5>
<p>Per diminuire le richieste http è una buona abitudine combinare più fogli di stile in uno solo. Si potrebbe fare manualmente, ma se in futuro vorrai effettuare delle modifiche dovrai modificare i singoli file e ricombinarli oppure modificare il file grande con la difficoltà di aver a che fare con centinaia di righe di codice.</p>
<p>Il metodo è quello di creare un file .css in cui inserire uno <strong>script php</strong> che permetta di stampare al suo interno tutti i file .css da te specificati. Dovrai inoltre impostare Apache affinché processi i file .css come file .php .</p>
<p>Per file dinamici di questo tipo sarà necessario richiamare più volte la funzione <em>header </em>all&#8217;inizio del file in modo da <strong>inviare i campi di intestazione</strong> riguardanti la gestione della cache.</p>
<p>Questo argomento farà parte del prossimo articolo su come combinare e ottimizzare immagini, css e script.</p>
<p><span id="script1">Ecco un <strong><em>semplice script php</em></strong>.</span></p>
<pre lang="php">&lt; ?
$files = array("css1.css","css2.css");
$mtime = 0;
$this_mtime = 0;
ob_start();
foreach($files as $file)
{
	if(file_exists($file))
	{
		include($file); /* includo il file */
		$this_mtime = filemtime($file); /* leggo la data dell'ultima modifica */
		if($mtime &lt; $this_mtime) $mtime=$this_mtime;
	}
}
$lenght = ob_get_length(); /* lunghezza del contenuto */
$content = ob_get_contents(); /* il contenuto nella variabile $content da stampare successivamente */ ob_end_clean();

/* Headers */
header("Content-Type: text/css");
header("Last-Modified: ".date("D, d M Y H:i:s",$mtime)." GMT");
header("Content-Length",$lenght);
header("ETag: ".md5("compressed.css".$lenght.$mtime)); /* il file si chiama compressed.css */
header("Cache-Control: max-age=345600");

/* Stampo il contenuto */
echo $content;
?&gt;</pre>
<ul>
<li>per calcolare l&#8217;ultima modifica da inviare nel campo di intestazione &#8220;Last-Modified&#8221; sarà quella del file che è stato modificato più recentemente</li>
<li>nell&#8217;ETag inserisco anche il nome del file per aumentare l&#8217;univocità dell&#8217;ETag</li>
</ul>
<p>Come ultima operazione inserire nel file .htaccess la riga:</p>
<p><code>AddHandler application/x-httpd-php .css</code></p>
<p>Questa riga fa in modo che Apache processi i file css come file php.</p>
<h5>Pagine dinamiche e database</h5>
<p>Quando una pagina &#8220;dinamica&#8221; ha sempre gli <strong>stessi dati per diversi giorni</strong> è importante fare in modo che un utente, a partire dalla seconda visita, non ricarichi una nuova versione di quella pagina ma legga la versione memorizzata in cache.</p>
<p>Nei cms, come in Wordpress, c&#8217;è una netta separazione fra template e codice. In alcuni non è possibile creare un template per una singola pagina per altri, come Wordpress, si. Tuttavia, secondo me, è totalmente inutile creare un template per scrivere solo i tag &lt;meta&gt; e avere una gestione personalizzata della cache per quella pagina. Per questo motivo conviene <strong>inviare i campi di intestazione all&#8217;interno del codice</strong>.</p>
<p>Una prima idea è quella di definire delle condizioni per cui dei record restituiti dal database devono essere considerati &#8220;vecchi&#8221;, e in base a queste ed altre condizioni inviare gli opportuni valori dei campi di intestazione.</p>
<h3>3. Configurare il web server Apache</h3>
<p><a href="http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html"><img class="alignright size-full wp-image-181" title="Apache Server" src="http://jblog.it/wp-content/uploads/2009/04/4229-apache-server.jpg" alt="Apache Server" width="172" height="83" /></a>Per gestire la cache con Apache è necessario caricare i moduli <strong>mod_expires</strong> e <strong>mod_headers</strong>.</p>
<h5>Caricare i moduli</h5>
<ul>
<li>cerca e apri il file <strong>httpd.conf</strong></li>
<li>individua la lunga lista di &#8220;mod_&#8230;&#8221;</li>
<li>individua le righe con &#8220;mod_expires&#8221; e &#8220;mod_header&#8221;</li>
<li>elimina (se c&#8217;è) il carattere &#8220;#&#8221; che si trova prima del nome dei moduli che vuoi attivare</li>
<li>riavvia il server Apache</li>
</ul>
<p>A questo punto, nel file <strong>.htaccess</strong> bisogna definire le regole che consentono di gestire la cache a seconda del tipo o estensione dei file richiesti durante le connessioni http.</p>
<h5>Il modulo mod_expires</h5>
<p>Per conoscere meglio questo modulo ti consiglio di andare a leggere la guida ufficiale di Apache (in inglese): <a rel="nofollow" href="http://httpd.apache.org/docs/2.2/mod/mod_expires.html">http://httpd.apache.org/docs/2.2/mod/mod_expires.html</a>.</p>
<h5>Il modulo mod_headers</h5>
<p>Per conoscere meglio questo modulo ti consiglio di andare a leggere la guida ufficiale di Apache (in inglese): <a rel="nofollow" href="http://httpd.apache.org/docs/2.2/mod/mod_headers.html">http://httpd.apache.org/docs/2.2/mod/mod_headers.html</a>.</p>
<h5>Gestione della cache in base all&#8217;estensione</h5>
<pre>ExpiresActive On
ExpiresDefault A300
&lt;FilesMatch ".html$"&gt;
	Expires A86400
&lt;/FilesMatch&gt;
&lt;FilesMatch ".(gif|jpg|png|js|css)$"&gt;
	Expires A2592000
&lt;/FilesMatch&gt;</pre>
<ul>
<li>la prima riga (<strong>ExpiresActive</strong>) attiva il modulo &#8220;mod_expires&#8221;</li>
<li>la seconda riga (<strong>ExpiresDefault</strong>) imposta un valore di default del campo di intestazione &#8220;Expires&#8221; pari a 300 secondi</li>
<li>il primo blocco &lt;FilesMatch&gt; fa in modo che tutti i file html abbiano il campo di intestazione &#8220;Expires&#8221; con il valore 86400 secondi</li>
<li>il secondo blocco &lt;FilesMatch&gt; fa in modo che tutti i file gif, jpg, png, js, css abbiano il campo di intestazione &#8220;Expires&#8221; con il valore 2592000 secondi</li>
<li>la lettera <strong>A</strong> indica che il valore viene impostato <strong>dopo l&#8217;accesso</strong> al file, mentre la lettera <strong>M</strong> imposterebbe il valore <strong>dopo la modifica</strong> al file</li>
</ul>
<p><strong>Svantaggi.</strong> Spesso capita che alcuni file, benché siano dello stesso tipo, abbiano estensioni diverse. Ad esempio, le immagini con una compressione Jpeg possono avere l&#8217;estensione jpg oppure jpeg. Quindi se capitasse un file jpeg non si avrebbe la corrispondenza.</p>
<h5>Gestione della cache in base al tipo MIME</h5>
<p>Per assicurarci di individuare tutti i file di un certo tipo è necessario leggere il loro tipo MIME.</p>
<pre>ExpiresActive On
ExpiresDefault A300
ExpiresByType text/css "access plus 1 day"
ExpiresByType text/javascript "access plus 3 days"
ExpiresByType image/png "access plus 2 months"</pre>
<h2>Forzare l&#8217;aggiornamento dei componenti</h2>
<p>Se si utilizzano dei componenti che devono essere sempre aggiornati spesso non basta scrivere i campi di intestazione <code>"Cache-Control: no-cache"</code> e <code>"Pragma: no-cache"</code>. Esistono infatti <strong>prove documentate</strong> sul fatto che a volte questi campi vengono <strong>ignorati dai browser</strong>.</p>
<p>Quando utilizzavo un <strong>script captcha</strong> notavo che non si aggiornava l&#8217;immagine, il che era davvero un problema in quanto se l&#8217;utente sbagliava il codice doveva ricaricarsi la pagina con una nuova immagine.</p>
<p>La <strong>soluzione</strong> consiste nello scrivere l&#8217;indirizzo dell&#8217;immagine con un elemento dipendente dal tempo. Quindi, invece di scrivere:<br />
<code>&lt;img src="myimage.jpg" alt="La mia immagine" /&gt;</code></p>
<p>si cambierà l&#8217;indirizzo in:<br />
<code>&lt;img src="myimage.jpg?&lt;? echo time(); ?&gt;" alt="La mia immagine" /&gt;</code><br />
dove la funzione <code>time()</code> restituisce data e ora attuali in numeri interi (ad es. 11022103710).</p>
<p>Nel caso si utilizzi l&#8217;<strong>immagine come sfondo</strong>, anziché scrivere:<br />
<code>&lt;div style="background:#000 url('img/blackback.png') no-repeat left bottom"&gt;&lt;/div&gt;</code></p>
<p>si dovrà modificare l&#8217;indirizzo in:<br />
<code>&lt;div style="background:#000 url('img/blackback.png?&lt;? echo time(); ?&gt;') no-repeat left bottom"&gt;&lt;/div&gt;</code></p>
<p>Uno dei <strong>possibili svantaggi</strong> sta nel fatto che non tutti i file possono essere processati con il compilatore php. Se vuoi che un file .js (javascript) o .css (foglio di stile) venga processato come un file php basterà aggiungere al file .htaccess le seguenti righe:</p>
<p><code>AddHandler application/x-httpd-php .css<br />
AddHandler application/x-httpd-php .js</code></p>
<p>Per concludere, scrivendo questo articolo ho scoperto un mondo riguardo la cache e la sua gestione, ed ho capito che gestire adeguatamente la cache permette di ottimizzare notevolmente il caricamento delle pagine di un sito web.</p>
<p>Come utilizzavi la cache fino ad oggi? Ti limitavi a scrivere i tre tag &lt;meta&gt; o avevi già pensato di iniziare a utilizzare la cache più seriamente? Ti sembra importante o è solo una mia impressione? L&#8217;articolo è scritto bene o manca qualcosa?</p>
<h6 class="highlight_red">Non perdere il prossimo articolo: &#8220;Ridurre le richieste HTTP (parte 2): combinare e ottimizzare immagini, script e css&#8221;.</h6>
<h4>Crediti</h4>
<ul>
<li><strong>Libro.</strong> Creare siti web ad alte prestazioni: <a rel="nofollow" href="http://www.tecnichenuove.com/libri/creare_siti_web_ad_alte_prestazioni.html" target="_blank">http://www.tecnichenuove.com/libri/creare_siti&#8230;</a></li>
<li>Guida ufficiale di Apache: <a rel="nofollow" href="http://httpd.apache.org/docs/2.2/" target="_blank">http://httpd.apache.org/docs/2.2/</a></li>
<li>Use Server Cache Control to Improve Performance: <a rel="nofollow" href="http://websiteoptimization.com/speed/tweak/cache/" target="_blank">http://websiteoptimization.com/speed/tweak/cache/</a></li>
<li>Foto1: <a rel="nofollow" href="http://www.flickr.com/photos/aureusbay/297387489/">http://www.flickr.com/photos/aureusbay/297387489/</a></li>
<li>Foto2: <a href="http://www.flickr.com/photos/thingsarebetterwithaparrott/1054908626/">http://www.flickr.com/photos/thingsarebetterwithaparrott/1054908626/</a></li>
<li>Foto3: <a rel="nofollow" href="http://www.flickr.com/photos/galopoulos/567890941/">http://www.flickr.com/photos/galopoulos/567890941/</a></li>
</ul>
<img src="http://jblog.it/?ak_action=api_record_view&id=124&type=feed" alt=" Ridurre le richieste HTTP (parte 1): come utilizzare la cache del browser"  title="Ridurre le richieste HTTP (parte 1): come utilizzare la cache del browser" />]]></content:encoded>
			<wfw:commentRss>http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>
