{"id":708,"date":"2017-03-06T11:31:54","date_gmt":"2017-03-06T10:31:54","guid":{"rendered":"https:\/\/alistapart.com\/it\/article\/usare-http2-responsabilmente-adattarsi-agli-utenti\/"},"modified":"2017-03-06T11:31:54","modified_gmt":"2017-03-06T10:31:54","slug":"usare-http2-responsabilmente-adattarsi-agli-utenti","status":"publish","type":"article","link":"https:\/\/alistapart.com\/it\/article\/usare-http2-responsabilmente-adattarsi-agli-utenti\/","title":{"rendered":"Usare HTTP\/2 Responsabilmente: adattarsi agli utenti"},"content":{"rendered":"<div class=\"main-content pre-article\">\n<p class=\"editors-note\"><strong>Nota degli editori:<\/strong> questo articolo \u00e8 la prima parte di una serie di due articoli che esplorano il nuovo protocollo HTTP\/2 e come usarlo responsabilmente. Leggete anche la seconda parte: <a href=\"http:\/\/alistapart.com\/article\/considering-how-we-use-http2\">Considerare come si usa HTTP\/2<\/a>.<\/p>\n<\/div>\n<p>\u00c8 importante ricordare che le ottimizzazioni specifiche per HTTP\/2 possono diventare degli svantaggi in termini di performance per gli utenti su HTTP\/1. Nella parte finale di questa serie, parleremo delle conseguenze sulla performance di una tale strategia e in che modo costruire tool che possano aiutarvi a gestire asset specifici per HTTP\/1 e HTTP\/2.<\/p>\n<p>Il nostro esempio generalizzato dal precedente articolo ci mostra in che modo possiamo adattare l&#8217;invio degli asset del sito alla connessione dell&#8217;utente. Ora, vediamo in che modo questo influenzi la performance nel mondo reale.<\/p>\n<div class=\"paragrafo\">\n<h2 id=\"section1\">Osservare i risultati della performance<\/h2>\n<h3 id=\"section2\">Sviluppare una metodologia di testing<\/h3>\n<p>Le connessioni mobile a bassa velocit\u00e0 sono piuttosto comuni nei paesi in via di sviluppo. Per pura curiosit\u00e0, volevo simulare degli scenari HTTP\/1 e HTTP\/2 con <a href=\"https:\/\/jeremywagner.me\/\">il mio sito<\/a> su una vera connessione mobile a bassa velocit\u00e0.<\/p>\n<p>Per una combinazione stranamente casuale degli eventi, ho finito i dati mobile ad alta velocit\u00e0 a mia disposizione nel mese in cui ho pianificato i test. Al posto di farmi pagare un extra, il mio provider riduce semplicemente la velocit\u00e0 di connessione al 2G. Dato il tempismo perfetto, ho fatto tethering con il mio iPhone e ho cominciato.<\/p>\n<p>Per misurare la performance in ogni scenario, vi serve una buona metodologia di testing. Volevo testare tre diversi scenari:<\/p>\n<ol>\n<li><strong>Sito ottimizzato per HTTP\/2:<\/strong> questa \u00e8 la strategia di ottimizzazione di default quando il sito viene inviato usando HTTP\/2. Se il protocollo rilevato \u00e8 HTTP\/2, viene inviato un numero pi\u00f9 alto di asset piccoli, granulari.<\/li>\n<li><strong>Sito non ottimizzato per HTTP\/1:<\/strong> si ha questo scenario quando HTTP\/2 non \u00e8 supportato dal browser e quando l&#8217;invio del contenuto non \u00e8 adattato in accordo a questi limiti. In altre parole, il contenuto e gli asset sono ottimizzati per l&#8217;invio su HTTP\/2, rendendoli tutt&#8217;altro che ottimali per gli utenti su HTTP\/1.<\/li>\n<li><strong>Sito ottimizzato per HTTP\/1:<\/strong> ai browser incompatibili con HTTP\/2 vengono fornite delle ottimizzazione per HTTP\/1 dopo che la strategia per l&#8217;invio dei contenuti si adatta a soddisfare i limiti del browser.<\/li>\n<\/ol>\n<p>Il tool che ho scelto per i test era <a href=\"https:\/\/www.sitespeed.io\/\">sitespeed.io<\/a>. sitespeed.io \u00e8 un ingegnoso tool da riga di comando, installabile con il package manager di Node (<code>npm<\/code>), pieno di opzioni per automatizzare i test di performance. Ogni volta che finisce una sessione, sitespeed.io raccoglie varie metriche di performance della pagina.<\/p>\n<p>Per raccogliere i dati di performance in ogni scenario, ho usato il seguente comando nella finestra del terminale:<\/p>\n<p><code>sitespeed.io -b chrome -n 200 --browsertime.viewPort 320x480 -c native -d 1 -m 1 https:\/\/jeremywagner.me<\/code><\/p>\n<p>Ci sono molte opzioni in questo caso, ma il succo \u00e8 che sto testando l&#8217;URL del mio sito usando Chrome. Il test verr\u00e0 fatto 200 volte per ciascuno dei tre scenari e user\u00e0 una dimensione della viewport di 320&#215;480. Per una lista completa delle opzioni di runtime di sitespeed.io, <a href=\"https:\/\/www.sitespeed.io\/documentation\/sitespeed.io\/configuration\/\">controllate la sua documentazione<\/a>.<\/p>\n<h3 id=\"section3\">I risultati del test<\/h3>\n<p>Stiamo tracciando tre aspetti della performance della pagina: il tempo totale impiegato per il caricamento della pagina, la quantit\u00e0 di tempo necessaria perch\u00e9 l&#8217;evento <code>DOMContentLoaded<\/code> parta sul client e il tempo necessario perch\u00e9 il browser cominci a fare l&#8217;operazione di painting della pagina.<\/p>\n<p>Per prima cosa, osserviamo i tempi di caricamento totale della pagina per ciascuno scenario (<strong>Fig. 1<\/strong>).<\/p>\n<div class=\"illustration full left\"><img decoding=\"async\" src=\"http:\/\/alistapart.com\/it\/wp-content\/uploads\/sites\/2\/2017\/03\/support-threshold-2x.jpg\" border=\"0\" alt=\"Grafico a barre dei risultati del test \u201cTotal Page Load Times\u201d per ciascuno dei tre scenari\" width=\"100%\" \/><\/p>\n<p>Fig. 1: I risultati del test \u201cTotal Page Load Times\u201d indicano una differenza significativa nella performance per gli scenari \u201cHTTP\/1 Unoptimized\u201d.<\/p>\n<\/div>\n<p>Questo grafico illustra un trend che vedrete pi\u00f9 avanti. Gli scenari ottimizzati per HTTP\/1 e HTTP\/2 dimostrano livelli simili di performance quando girano sulle loro rispettive versioni del protocollo. Lo scenario pi\u00f9 lento gira su HTTP\/1, tuttavia \u00e8 stato ottimizzato per HTTP\/2.<\/p>\n<p>In questi grafici, stiamo progettando due stime: la media e il novantacinquesimo percentile (che significa che i tempi di caricamento sono sotto a questo valore il 95% delle volte). Quello che questi dati mi dicono \u00e8 che se spostassi il mio sito su HTTP\/2 ma non lo ottimizzassi per i browser che non sono compatibili con HTTP\/2, il tempo di caricamento medio della pagina per quel segmento di utenti sarebbe il 10% pi\u00f9 lento il 95% delle volte. E il 5% delle volte, il caricamento della pagina potrebbe essere pi\u00f9 lento del <em>15%<\/em>.<\/p>\n<p>Per un sito piccolo e poco complicato come il mio blog questo risultato potrebbe sembrare insignificante, ma in realt\u00e0 non lo \u00e8. E se sul mio sito arrivasse molto traffico? Cambiare il modo in cui invio il contenuto perch\u00e9 sia pi\u00f9 inclusivo per gli utenti con capacit\u00e0 limitate potrebbe fare la differenza tra un utente che rimane e uno che decide di andarsene perch\u00e9 ha aspettato troppo.<\/p>\n<p>Diamo un&#8217;occhiata a quanto ci vuole perch\u00e9 il DOM sia pronto in ciascuno scenario (<strong>Fig. 2<\/strong>).<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/alistapart.com\/it\/wp-content\/uploads\/sites\/2\/2017\/03\/domcontentloadtime.jpg\" border=\"0\" alt=\"Grafico a barre per i risultati del test \u201cDOM Content Loaded Time\u201d per ciascuno dei tre scenari\" width=\"100%\" \/> Fig. 2: I risultati del test DOMContentLoaded Time indicano una differenza significativa nella performance per gli scenari ottimizzati per HTTP\/1.<\/p>\n<p>Nuovamente, vediamo livelli simili di performance quando un sito \u00e8 ottimizzato per il suo particolare protocollo. Per lo scenario nel quale il sito \u00e8 ottimizzato per HTTP\/2 ma gira su HTTP\/1, l&#8217;evento <code>DOMContentLoaded<\/code> si attiva il 10% pi\u00f9 lentamente rispetto a ciascuno degli scenari \u201cottimali\u201d. Questo capita il 95% delle volte. Tuttavia, il 5% delle volte, potrebbe essere pi\u00f9 lento addirittura del <em>26%<\/em>.<\/p>\n<p>E per quello che riguarda il tempo per il primo paint? Probabilmente questa \u00e8 la metrica di performance pi\u00f9 importante perch\u00e9 \u00e8 il primo punto in cui l&#8217;utente <em>vede<\/em> effettivamente il vostro sito web. Cosa succede a questa metrica quando ottimizziamo la nostra strategia di content delivery per ogni versione del protocollo? (<strong>Fig. 3<\/strong>)<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/alistapart.com\/it\/wp-content\/uploads\/sites\/2\/2017\/03\/firstpainttime.jpg\" border=\"0\" alt=\"Grafico a barre dei risultati del test \u201cFirst Paint Time\u201d per ciascuno dei tre scenari\" width=\"100%\" \/> Fig. 3: I risultati del test \u201cFirst Paint Time\u201d indicano una differenza significativa nella performance per gli scenari HTTP\/1 Unoptimized.<\/p>\n<p>Il trend persiste di nuovo. Nello scenario HTTP\/1 Unoptimized, il paint time \u00e8 del 10% pi\u00f9 lungo che in ciascuno degli scenari ottimizzati il 95% delle volte e quasi due volte quella durata durante l&#8217;altro 5%.<\/p>\n<p>Un ritardo del 10-20% nel page paint time \u00e8 una cosa seria. Se aveste la possibilit\u00e0 di accelerare il rendering per un segmento significativo del vostro pubblico, non vorreste farlo?<\/p>\n<p>Un altro modo per migliorare questa metrica per gli utenti su HTTP\/1 \u00e8 di implementare un CSS critico. Per me \u00e8 un&#8217;opzione dal momento che il CSS del mio sito \u00e8 2.2KB dopo la compressione Brotli. Sui si HTTP\/2, potete ottenere dei benefit di performance simili all&#8217;inlining utilizzando la feature Server Push del protocollo.<\/p>\n<p>Ora che abbiamo esaminato le implicazioni di performance dell&#8217;adeguare l&#8217;invio del contenuto alla versione del protocollo HTTP dell&#8217;utente, impariamo come generare automaticamente degli asset ottimizzati per entrambe i segmenti dei vostri utenti.<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2 id=\"section4\">Un aiuto dai build tools<\/h2>\n<p>Siete gi\u00e0 abbastanza presi, lo so. Mantenere due insiemi di asset ottimizzati per due diversi tipi di utenti suona come un grande impegno, ma qui \u00e8 dove entrano in gioco i build tool come <a href=\"http:\/\/gulpjs.com\/\">gulp<\/a>.<\/p>\n<p>Se usate gulp (o altri tool di automazione come <a href=\"http:\/\/gruntjs.com\/\">Grunt<\/a> o <a href=\"https:\/\/webpack.github.io\/\">webpack<\/a>), ci sono buone probabilit\u00e0 che stiate gi\u00e0 automatizzando cose come la minimizzazione degli script (o <a href=\"http:\/\/stackoverflow.com\/questions\/19694448\/grunt-whats-the-difference-between-concat-and-uglify-and-minify\/19694522#19694522\">uglification<\/a>, a seconda di quanto sono aggressive le vostre ottimizzazioni). Quello che segue \u00e8 un esempio generalizzato del modo in cui potreste usare i plugin <a href=\"https:\/\/www.npmjs.com\/package\/gulp-uglify\"><code>gulp-uglify<\/code><\/a> e <a href=\"https:\/\/www.npmjs.com\/package\/gulp-concat\"><code>gulp-concat<\/code><\/a> per fare l&#8217;uglify dei files e poi concatenare quegli asset \u201cuglified\u201d separati in uno unico.<\/p>\n<pre id=\"snippet1\" class=\" language-javascript\"><code class=\" language-javascript\"><span class=\"token keyword\">var<\/span> gulp <span class=\"token operator\">=<\/span> require<span class=\"token punctuation\">(<\/span><span class=\"token string\">\"gulp\"<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span>\n   uglify <span class=\"token operator\">=<\/span> require<span class=\"token punctuation\">(<\/span><span class=\"token string\">\"gulp-uglify\"<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span>\n   concat <span class=\"token operator\">=<\/span> require<span class=\"token punctuation\">(<\/span><span class=\"token string\">\"gulp-concat\"<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token comment\">\/\/ Uglification\n<\/span>gulp<span class=\"token punctuation\">.<\/span>task<span class=\"token punctuation\">(<\/span><span class=\"token string\">\"uglify\"<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">function<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">{<\/span>\n   <span class=\"token keyword\">var<\/span> src <span class=\"token operator\">=<\/span> <span class=\"token string\">\"src\/js\/*.js\"<\/span><span class=\"token punctuation\">,<\/span>\n       dest <span class=\"token operator\">=<\/span> <span class=\"token string\">\"dist\/js\"<\/span><span class=\"token punctuation\">;<\/span>\n\n   <span class=\"token keyword\">return<\/span> gulp<span class=\"token punctuation\">.<\/span>src<span class=\"token punctuation\">(<\/span>src<span class=\"token punctuation\">)<\/span>\n       <span class=\"token punctuation\">.<\/span>pipe<span class=\"token punctuation\">(<\/span>uglify<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span>\n       <span class=\"token punctuation\">.<\/span>pipe<span class=\"token punctuation\">(<\/span>gulp<span class=\"token punctuation\">.<\/span>dest<span class=\"token punctuation\">(<\/span>dest<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token comment\">\/\/ Concatenation\n<\/span>gulp<span class=\"token punctuation\">.<\/span>task<span class=\"token punctuation\">(<\/span><span class=\"token string\">\"concat\"<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">\"uglify\"<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">function<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">{<\/span>\n   <span class=\"token keyword\">var<\/span> src <span class=\"token operator\">=<\/span> <span class=\"token string\">\"dist\/js\/*.js\"<\/span><span class=\"token punctuation\">,<\/span>\n       dest <span class=\"token operator\">=<\/span> <span class=\"token string\">\"dist\/js\"<\/span><span class=\"token punctuation\">;<\/span>\n\n   <span class=\"token keyword\">return<\/span> gulp<span class=\"token punctuation\">.<\/span>src<span class=\"token punctuation\">(<\/span>src<span class=\"token punctuation\">)<\/span>\n       <span class=\"token punctuation\">.<\/span>pipe<span class=\"token punctuation\">(<\/span>concat<span class=\"token punctuation\">(<\/span><span class=\"token string\">\"script-bundle.js\"<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span>\n       <span class=\"token punctuation\">.<\/span>pipe<span class=\"token punctuation\">(<\/span>gulp<span class=\"token punctuation\">.<\/span>dest<span class=\"token punctuation\">(<\/span>dest<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<p>In questo esempio, tutti gli script nella directory <code>src\/js<\/code> sono \u201cuglified\u201d dal task <code>uglify<\/code>. Ogni script processato viene inviato separatamente su <code>dist\/js<\/code>. Quando questo accade, il task <code>concat<\/code> si attiva e raggruppa tutti questi script in un singolo file chiamato <code>script-bundle.js<\/code>. Potete poi usare la tecnica di protocol detection mostrata nella prima parte di questa serie di articoli per cambiare gli script che vengono inviati a seconda della versione del protocollo del visitatore.<\/p>\n<p>Ovviamente, questa non \u00e8 l&#8217;unica cosa che potete fare con un build system. Potete usare lo stesso approccio per raggruppare i vostri files CSS o addirittura generare delle image sprite da immagini separate con il plugin <a href=\"https:\/\/www.npmjs.com\/package\/gulp.spritesmith\"><code>gulp.spritesmith<\/code><\/a>.<\/p>\n<p>Il punto qui \u00e8 che un build system rende semplice mantenere due insiemi di asset ottimizzati (tra le molte altre cose, ovviamente). Pu\u00f2 essere fatto facilmente ed automaticamente, permettendovi di concentrarvi sullo sviluppo e sul miglioramento della performance per i visitatori del vostro sito.<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2 id=\"section5\">Riflessioni<\/h2>\n<p>Abbiamo visto come un sito ottimizzato per HTTP\/2 possa avere una performance scarsa per gli utenti con browser incompatibili con HTTP\/2.<\/p>\n<p>Ma <em>perch\u00e9<\/em> le capacit\u00e0 di questi utenti sono limitate? Dipende, davvero.<\/p>\n<p>Le condizioni socio-economiche hanno un ruolo nella faccenda. Gli utenti tendono a comprare il tipo di device che possono permettersi, quindi le capacit\u00e0 del device \u201cmedio\u201d varia in maniera significativa, specialmente tra le nazioni in via di sviluppo e quelle pi\u00f9 avanzate.<\/p>\n<p>La mancanza di risorse finanziarie potrebbe inoltre guidare gli utenti a piani dati ristretti e i browser come Opera Mini che minimizzano l&#8217;uso di dati. Finch\u00e9 questi browser non supporteranno HTTP\/2, una percentuale significativa di utenti l\u00e0 fuori potrebbero non tornare pi\u00f9.<\/p>\n<p>Per qualcuno potrebbe anche essere problematico aggiornare le app con un piano dati ristretto. Non ci si pu\u00f2 aspettare l&#8217;adozione immediata e alcuni potrebbero rinunciare ad aggiornare il browser per risparmiare dati nel loro piano. Nelle nazioni in via di sviluppo, la qualit\u00e0 dell&#8217;infrastruttura internet \u00e8 significativamente pi\u00f9 indietro rispetto al resto del mondo pi\u00f9 sviluppato.<\/p>\n<p>Non possiamo cambiare il comportamento di ogni utente perch\u00e9 segua le nostre preferenze di sviluppo. Quello che <em>possiamo<\/em> fare, per\u00f2, \u00e8 identificare i segmenti di pubblico che non possono supportare HTTP\/2, poi prendere una decisione oculata se vale la pena oppure no adattare il modo in cui inviamo loro il contenuto. Se una porzione considerevole del pubblico usa dei browser incompatibili con HTTP\/2, possiamo cambiare il modo in cui inviamo loro il contenuto. Possiamo inviargli un&#8217;esperienza ottimizzata e favorirli, e possiamo farlo mentre forniamo dei vantaggi in termini di performance per quegli utenti che <em>possono<\/em> supportare HTTP\/2.<\/p>\n<p>Ci sono molte persone l\u00e0 fuori che affrontano sfide significative mentre navigano nel web. Prima di adottare completamente le nuove tecnologie, cerchiamo di capire in che modo possiamo farlo senza piantare in asso un segmento significativo del nostro pubblico. La ricompensa per quello che facciamo deriva dal fornire soluzioni che funzionano per <em>tutti<\/em>. Adottiamo le nuove tecnologie responsabilmente. Sta a noi agire con cura.<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2 id=\"section6\">Ulteriori letture<\/h2>\n<p>Imparate come aumentare la performance del vostro sito con il libro di Jeremy <a href=\"https:\/\/www.manning.com\/books\/web-performance-in-action?a_aid=webopt&amp;a_bid=63c31090\">Web Performance in Action<\/a>. Avrete il 39% di sconto usando il codice <strong>ALAWPA<\/strong>.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>A seconda delle capacit\u00e0 del vostro pubblico, un sito ottimizzato per HTTP\/2 potrebbe essere dannoso per un segmento dei vostri utenti. Jeremy Wagner ci mostra come l&#8217;adaptive content delivery possa migliorare la performance del sito dovuta a browser incompatibili.<\/p>\n","protected":false},"author":818,"featured_media":0,"comment_status":"open","ping_status":"open","template":"","categories":[242,4,270,173],"tags":[],"coauthors":[500],"class_list":["post-708","article","type-article","status-publish","hentry","category-browser","category-codice","category-il-server-side","category-numero-195-23-febbraio-2017"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/article\/708","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/article"}],"about":[{"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/types\/article"}],"author":[{"embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/users\/818"}],"replies":[{"embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/comments?post=708"}],"wp:attachment":[{"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/media?parent=708"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/categories?post=708"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/tags?post=708"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/coauthors?post=708"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}