{"id":378,"date":"2013-05-27T08:14:11","date_gmt":"2013-05-27T06:14:11","guid":{"rendered":"https:\/\/alistapart.com\/it\/article\/piccola-guida-all-utilizzo-di-node\/"},"modified":"2013-05-27T08:14:11","modified_gmt":"2013-05-27T06:14:11","slug":"piccola-guida-all-utilizzo-di-node","status":"publish","type":"article","link":"https:\/\/alistapart.com\/it\/article\/piccola-guida-all-utilizzo-di-node\/","title":{"rendered":"Piccola guida all&#8217;utilizzo di Node"},"content":{"rendered":"<div class=\"paragrafo\">\n<p><img decoding=\"async\" src=\"http:\/\/alistapart.com\/it\/wp-content\/uploads\/sites\/2\/2013\/05\/n74a2web.png\" border=\"0\" align=\"left\" \/>Nel mio primo articolo, \u201c<a href=\"articoli\/90-numero-74-27-maggio-2013\/377-migliori-mockup-nel-browser-con-nodejs\">Migliori mockup nel browser con Node.js<\/a>\u201d, ho spiegato perch\u00e9 Node.js rende pi\u00f9 semplice la progettazione di applicazioni e come cominciare. Adesso \u00e8 il momento di vedere il nuovo processo di design in azione.<\/p>\n<p>Piuttosto che cercare di capire tutti i requisiti e gli schemi API solo per realizzare i comp con del contenuto fittizio inserito direttamente nel codice e con interazioni fittizie con il server, per poi dover buttare via tutto quando si tratta di dover implementare le cose &#8220;realmente&#8221;. Con Node.js potete evitare l&#8217;inserimento del contenuto e produrre codice lato client pronto per la beta version.<\/p>\n<p>Il processo sembra un po&#8217; il buon vecchio <a href=\"articoli\/77-numero-63-7-novembre-2012\/321-responsive-comp-ottenere-contratto-senza-mockup\">design nel browser<\/a>, ma con pi\u00f9 JavaScript e con un livello aggiunti:<\/p>\n<ol>\n<li>Design del layout e degli stili<\/li>\n<li>Convertire il markup in un template JavaScript<\/li>\n<li>Crere una funzione di inizializzazione<\/li>\n<li>Creare un semplice server Node.js<\/li>\n<li>Aggiungere al server un modello di &#8220;data object&#8221;<\/li>\n<li>Aggiungere le funzioni server per mandare pagine statice e JSON<\/li>\n<li>Richiedere e utilizzare il JSON lato client<\/li>\n<\/ol>\n<p>Vi spaventa? Non preoccupatevi: il primo step richiede un&#8217;infinit\u00e0 di tempo in pi\u00f9 rispetto a qualunque altro step, quindi se avete gi\u00e0 il design, troverete tutti gli altri step molto pi\u00f9 che gestibili.<\/p>\n<p>In questa guida, creeremo una feature per un finto negozio d&#8217;arte. Se volete seguire il tutto passo passo da casa, potete clonare il mio <a href=\"https:\/\/github.com\/garann\/coolartstore\">repository GitHub<\/a>. (Se avete bisogno di una mano per l&#8217;installazione, leggete il <a href=\"https:\/\/github.com\/garann\/coolartstore\/blob\/master\/README.md\">README<\/a>, o date una sbirciata alla <a href=\"http:\/\/coolartstore.rs.af.cm\/\">live demo<\/a>. Spiegher\u00f2 pi\u00f9 avanti tutti gli step e commenter\u00f2 il codice qui sotto.)<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2>Creare i template<\/h2>\n<p>Una volta che avete un design robusto e il markup che lo accompagna, convertirlo in un template che potete usare per tutti gli esempi \u00e8 pi\u00f9 efficiente che creare un markup duplicato per ciascuno. La parte difficile \u00e8 finita: avete gi\u00e0 pensato a dove verranno usati i data point nel design che avete realizzato. Con queste scelte ancora fresche nella vostra mente, andate indietro e contrassegnate l&#8217;HTML con i dati nel linguaggio di template che preferite.<\/p>\n<p>Per il mio esempio, user\u00f2 un negozio che vende stampe artistiche. Ecco una snippet del mio markup iniziale:<\/p>\n<pre><code>&lt;h2&gt;Two Acrobats with a Dog&lt;\/h2&gt;\n&lt;h3&gt;Pablo Picasso&lt;\/h3&gt;\n&lt;img src=\"img\/102.jpg\" alt=\"Two Acrobats with a Dog\" class=\"active\" \/&gt;\n&lt;ul class=\"info\"&gt;\n\t&lt;li&gt;8\" x 11\"&lt;\/li&gt;\n\t&lt;li&gt;acid-free paper&lt;\/li&gt;\n\t&lt;li&gt;suitable for matting&lt;\/li&gt;\n&lt;\/ul&gt;\n&lt;span class=\"price\"&gt;$49.99&lt;\/span&gt;<\/code><\/pre>\n<p>Pensate ai vostri template come a posti in cui definire i requisiti sia per i dati sia per la loro formattazione lato client. \u00c8 fantastico se potete anche riutilizzarli per il rendering client-side, ma potrebbe non essere rilevante per la vostra applicazione. Fintanto che avrete dei buoni dati, \u00e8 irrilevante convertirli da un linguaggio di template all&#8217;altro, quindi non state a tormentarvi troppo su quale template engine usare.<\/p>\n<p>Tuttavia, avete bisogno di un template engine che funzioni sia nel browser sia in Node.js. Se non siete sicuri, cercate il vostro template engine su <a href=\"https:\/\/github.com\/\">GitHub<\/a> e verificate che ci sia una guida per l&#8217;installazione via <a href=\"https:\/\/npmjs.org\/\">npm<\/a> nel manuale, cos\u00ec come uno script minified per l&#8217;utilizzo sul client. Io prediligo <a href=\"http:\/\/olado.github.io\/doT\/index.html\">doT.js<\/a>, quindi ecco di nuovo quella snipped con il markup per aggiungere i dati mediante doT:<\/p>\n<pre><code>&lt;h2&gt;{{=it.title}}&lt;\/h2&gt;\n&lt;h3&gt;{{=it.artist.name}}&lt;\/h3&gt;\n&lt;img src=\"img\/{{=it.id}}.jpg\" alt=\"{{=it.title}}\" class=\"active\" \/&gt;\n&lt;ul class=\"info\"&gt;\n\t{{~it.info :info_item}}\n\t&lt;li&gt;{{=info_item}}&lt;\/li&gt;\n\t{{~}}\n&lt;\/ul&gt;\n&lt;span class=\"price\"&gt;{{=it.price}}&lt;\/span&gt;<\/code><\/pre>\n<p>Mi piace salvare i miei template nella loro directory allo stesso livello della mia directory JavaScript, cos\u00ec adesso lo salvo come <code>tmpl\/detail.dot<\/code>.<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2>Inizializzare il client<\/h2>\n<p>Dal momento che vogliamo essere in grado di usare i nostri template sia in Node sia nel browser, hanno bisogno di essere memorizzati fuori dall&#8217;HTML e caricati e compilati quando apriamo la pagina. Per cominciare, salviamo la versione minified del template engine e aggiungiamo un tag script alla pagina, per includerlo. Una volta fatto ci\u00f2, potete caricare il template, compilarlo e poi continuare con qualunque altro lavoro di inizializzazione nel vostro file JavaScript principale. Sto usando jQuery nel mio esempio, pertanto il mio codice ha questo aspetto:<\/p>\n<pre><code>var detailTmpl;\n\n$.when( \n\t$.get( \"tmpl\/detail.dot\", function( tmpl ) {\n\t\tdetailTmpl = doT.template( tmpl );\n\t}, \"text\" ) \n).then( init );<\/code><\/pre>\n<p>Cos&#8217;\u00e8 quella misteriosa funzione <code>init<\/code>? \u00c8 dove metto qualsiasi interazione che voglio aggiungere al mio mockup statico. Per il momento sto solo creando un&#8217;interazione, quindi la mia funzione <code>init<\/code> \u00e8 piuttosto semplice:<\/p>\n<pre><code>function init() {\n\t$( \"div.content\" ).on( \"click\", \"div.result\", showDetail );\n}<\/code><\/pre>\n<p>Questo codice pu\u00f2 essere reso molto pi\u00f9 elegante usando <a href=\"http:\/\/requirejs.org\/\">Require.js<\/a> con il suo text plugin. Questo va oltre lo scopo di questa demo, ma vi incoraggio vivamente ad utilizzarlo in produzione.<\/p>\n<p>Gestiremo il rendering del template in <code>showDetail()<\/code>, ma dobbiamo aggiungere un server e un data store prima di scrivere quella funzione dal momento che adesso ci mancano i dati <em>da<\/em> rendere.<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2>Creare un server<\/h2>\n<p>Se ricarico adesso la mia pagina e apro la console del browser, ottengo un errore JavaScript. Questo succede perch\u00e9 sto cercando di caricare il mio template con una XMLHttpRequest (XHR) su una pagina che viene servita dal file system, in violazione alla <a href=\"http:\/\/en.wikipedia.org\/wiki\/Same_origin_policy\">same origin policy<\/a>. Non posso nemmeno controllare che il mio template funzioni finch\u00e8 non viene correttamente gestita (ad esempio, da un server).<\/p>\n<p>Per creare un semplice server Node che mi permetta di far girare il mio XHR, faccio alcune cose:<\/p>\n<ul>\n<li>Sposto tutti i miei asset esistenti in una nuova sottodirectory chiamata <code>public<\/code><\/li>\n<li>Apro il terminale o la riga di comando sulla directory di lavoro e scrivo <code>npm install express<\/code><\/li>\n<li>Aggiungo un file server.js alla directory di lavoro<\/li>\n<\/ul>\n<p>Potremmo scrivere tutto da zero, ovviamente, ma non \u00e8 necessario per un server base. Il framework <a href=\"http:\/\/expressjs.com\/\">Express<\/a> fornisce un numero di astrazioni di concetti e applicazioni server. Per la versione iniziale del server, l&#8217;unica di cui abbiamo bisogno \u00e8 la sua capacit\u00e0 di servire risorse statiche. Possiamo usarlo per aggiungere quattro righe di codice a <code>server.js<\/code>:<\/p>\n<pre><code>var express = require( \"express\" ),\n\tapp = express();\n\napp.use( express.static( __dirname + \"\/public\" ) );\n\napp.listen( 3000 );<\/code><\/pre>\n<p>Una volta che si avvia il server scrivendo <code>node server.js<\/code> nel terminale o nella riga di comando che abbiamo aperto, si pu\u00f2 vedere la propria pagina su http:\/\/localhost:3000 (aggiungere un filename se necessario) e l&#8217;errore relativo al caricamento del template dovrebbe essere scomparso.<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2>Aggiungere dati server-side<\/h2>\n<p>\u00c8 sicuramente positivo essere in grado di usare XHR, ma noi stiamo creando il server Node per usarlo come una rappresentazione del vero server e i veri server memorizzano dati. Sebbene non sia difficile creare un data store che funzioni con un sever Node, \u00e8 ancora meno difficle crearne un grande <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/JavaScript\/Guide\/Values,_variables,_and_literals?redirectlocale=en-US&amp;redirectslug=Core_JavaScript_1.5_Guide\/Values,_Variables,_and_Literals%23Object_literals\">object literal<\/a>. Per un mockup, \u00e8 tutto quello di cui abbiamo bisogno. Uno degli obiettivi qui consiste nel definire i data object che abbiamo bisogno di supportare nel nostro nuovo design, quindi il formato di questo oggetto pu\u00f2 essere determinato dal template che abbiamo appena aggiunto. Per esempio, ho bisogno di un oggetto strutturato, qualcosa cos\u00ec:<\/p>\n<pre><code>var products = {\n\t\"102\": {\n\t\tid: 102,\n\t\ttitle: \"Two Acrobats with a Dog\",\n\t\tartist: {\n\t\t\tname: \"Pablo Picasso\"\n\t\t},\n\t\tprice: \"$49.99\",\n\t\tinfo: [\n\t\t\t\"8\\\" x 11\\\"\",\n\t\t\t\"acid-free paper\",\n\t\t\t\"suitable for matting\"\n\t\t]\n\t}\n};<\/code><\/pre>\n<p>Notate che <code>products<\/code> potrebbe tranquillamente essere un array, ma io voglio poter trovare rapidamente i miei prodotti per ID, una volta che ne avr\u00f2 pi\u00f9 di uno nel mio finto data store. A parte questo piccolo colpo di scena, i dati appaiono esattamente come il contenuto hard-coded nel mio HTML originale. Se voglio aggiungere altri dati, incluse cose che potrebbero rompere il layout in modi imprevedibili, posso semplicemente copiare questa struttura e fare delle sostituzioni. Beh, pi\u00f9 o meno.<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2>Far ritornare i dati dal server<\/h2>\n<p>Se avete gi\u00e0 avuto a che fare con altri framework server-side, creare degli endpoint per XHR potrebbe fare paura, ma Express lo rende facilissimo. Non abbiamo bisogno di alcun setup speciale per definire un server endpoint come target di una richiesta asincrona. Tutto ci\u00f2 che dobbiamo fare \u00e8 definire il percorso sul server dove volete accettare le richieste e un callback. Il callback riceve un request object (per fare cose come ottenere i dati che sono stati passati) e un response object (per definire quello che ritorniamo al client). Per ritornare i dati nel mio oggetto products, aggiungo alcune righe di codice alla fine di server.js:<\/p>\n<pre><code>app.get( \"\/detail\/:id\", function( req, res ) {\n\tres.send( products[ req.params.id ] );\n});\n\napp.listen( 3000 );<\/code><\/pre>\n<p>Visto? Facile. Se faccio ripartire il server e vado su http:\/\/localhost:3000\/detail\/102, dovrei vedere il mio object data. Per analizzare quello che succede con l&#8217;ID nel path, abbiamo chiamato i dati in quella posizione nel path &#8220;id&#8221; con il pezzo <code>:id<\/code>, che poi \u00e8 disponibile come una propriet\u00e0 di <code>reg.params<\/code>.<\/p>\n<p>I nomi e le posizioni dei parametri dipendono da noi e se il nostro percorso fosse super complesso, potremmo usare anche le espressioni regolari per splittare molteplici pezzi di dati. Express ci d\u00e0 anche la possibilit\u00e0 di accettare dati dalla stringa della query o da un POST. Di tutti i pezzi che stiamo creando, comunque, i path sono quelli che pi\u00f9 probabilmente cambieranno in produzione, perci\u00f2 \u00e8 a vantaggio nostro mantenerli quanto pi\u00f9 leggibili possibile.<\/p>\n<p>Oltre a mandare dei puri dati al client, vogliamo anche essere in grado di mandare l&#8217;HTML, in caso un utente venga linkato direttamente ai dettagli del prodotto o non abbia JavaScript a sua disposizione. Potremmo anche volere HTML per il nostro proprio uso via XHR, se troviamo che il rendering client-sia ci rallenti troppo. Quindi, aggiungiamo un secondo endpoint sotto a quello che abbiamo creato, proprio per questo scopo:<\/p>\n<pre><code>app.get( \"\/product\/:id\", function( req, res ) {\n\tres.render( \"detail\", products[ req.params.id ] );\n});<\/code><\/pre>\n<p>Per amore della semplicit\u00e0 e poich\u00e9 il primo path ha servito JSON per un overlay mentre questo fornisce un&#8217;intera pagina, ho utilizzato diversi nomi di percorso, ma ho tenuto lo stesso pattern. Questa volta, invece della funzione di invio della risposa, uso <code>render()<\/code>. Express fornisce un po&#8217; di magia per far s\u00ec che il rendering del template funzioni da subito, ma dal momento che sto usando doT invece di Jade (il template engine di default di Express), devo fare del setup aggiuntivo.<\/p>\n<p>Per prima cosa devo tornare nel terminale o alla riga di comando, fermare il server Node ed installare il mio template engine usando <code>npm install doT<\/code> e il modulo consolidate (che fornisce a Express la compatibilit\u00e0 con un certo numero di template engine molto comuni) utilizzando <code>npm install consolidate<\/code>. Adesso li ho entrambe nella mia directory <code>node_modules<\/code> e posso usarli in <code>server.js<\/code>.<\/p>\n<p>Dal momento che si accede a doT (e probabilmente anche al template engine che avete scelto) attraverso consolidate, l&#8217;unico modulo aggiuntivo che devo richiedere all&#8217;inizio di <code>server.js<\/code> \u00e8 consolidate.<\/p>\n<pre><code>var express = require( \"express\" ),\n\tapp = express(),\n\tcons = require( \"consolidate\" );<\/code><\/pre>\n<p>Voglio continuare a mandare alcune delle mie altre pagine staticamente, quindi aggiungo i parametri di configurazione del template sotto la riga <code>app.use<\/code> gi\u00e0 presente nel mio codice:<\/p>\n<pre><code>app.use( express.static( _dirname + \"\/public\" ) );\napp.engine( \"dot\", cons.dot );\napp.set( \"view engine\", \"dot\" );\napp.set( \"views\", _dirname + \"\/public\/tmpl\" );<\/code><\/pre>\n<p>Quelle tre nuove righe impostano doT (cos\u00ec come viene esposto da consolidate) come il view engine, registrano i file che terminano in <code>.dot<\/code> come template e dicono a Express di cercare i template da usare in <code>\/public\/tmpl<\/code>. Quindi, quando Node vede <code>res.render( \"detail\", { ... } )<\/code>, sa come espandere <code>\"detail\"<\/code> in <code>\/public\/tmpl\/detail.dot<\/code> e renderlo come un template doT. Ora posso far ripartire il mio server, andare su http:\/\/localhost:3000\/product\/102 e vedere il mio template reso staticamente, senza dover creare un file server-side separato.<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2>Fetch dei dati dinamici<\/h2>\n<p>Il nostro template funziona ora come una pagina statica, ma c&#8217;\u00e8 un altro step per far s\u00ec che il nostro mockup venga popolato con i dati dal server. Ricordate la funzione <code>showDetail<\/code> del nostro script client-side principale? \u00c8 ora di approfondirla.<\/p>\n<p>Nel mio semplice esempio, l&#8217;overlay che verr\u00e0 popolato dal mio template esiste di gi\u00e0 come <code>div<\/code> nascosto sulla pagina principale e appare quando l&#8217;utente clicca su un <code>div<\/code> che contiene un riassunto del contenuto. Questo div ha un attributo data in cui memorizzare l&#8217;ID del prodotto che corrisponde alla propriet\u00e0 key e id nel mio data object lato server. Una volta che avviene l&#8217;evento click e viene richiamato <code>showDetail()<\/code>, ho solo bisogno di fare quanto segue:<\/p>\n<pre><code>function showDetail( e ) {\n\tvar id = $( this ).data( \"id\" );\n\t$.get( \"detail\/\" + id, function( info ) {\n\t\t$( \"div.detail\" ).html( detailTmpl( info ) );\n\t\t$( \"div.detail\" ).show();\n\t}\n}<\/code><\/pre>\n<p>Il path di cui sopra \u00e8 lo stesso che ho definito in <code>server.js<\/code>. Se avete scelto un nome diverso per il vostro, usate quel nome nel client. Quando ricevo il data object dal mio server, lo passo a <code>detailTmpl()<\/code>, la versione compilata del mio template. Il risultato della funzione <code>detailTmpl<\/code> \u00e8 l&#8217;HTML che deve popolare il mio overlay.<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2>Avanti<\/h2>\n<p>Ecco fatto! Un mockup che imita le interazioni che ci saranno con il server di produzione ma sul client, senza il bisogno di avere dati inseriti nel codice o workaround temporanei. Nonostante il semplice esercizio, il processo che ho delineato illustra una buona parte del setup necessario per creare altri workflow che richiedono interazioni lato server. Per esempio, posso riempire il mio finto data store con pi\u00f9 prodotti e usarlo per restituire la pagina iniziale che attiva il mio overlay senza dover rivisitare i dati fittizi e la mia applicazione mostrer\u00e0 i valori corretti in qualunque view che gli aggiungo.<\/p>\n<p>Se volete esplorare oltre l&#8217;utilizzo di HTML e JSON, considerate l&#8217;aggiunta di <a href=\"http:\/\/socket.io\">Socket.io<\/a> per permettere l&#8217;interazione real-time con pi\u00f9 client o Require.js per gestire gli asset sul client. Potreste anche spostare il CSS in template e mandare differenti build del vostro sito a diversi browser o device. Il vostro mockup pu\u00f2 essere tanto sofisticato e riflettere quanti pi\u00f9 requisiti di prodotto volete. Alla fine, la parte del leone del vostro codice client-side \u00e8 fatta e pronta all&#8217;uso.<\/p>\n<p>Illustrazioni: {carlok}<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In Migliori mockup nel browser con Node.js, Garann Means ci ha spiegato perch\u00e9 Node.js rende pi\u00f9 facile ed efficiente la progettazione di applicazione e come cominciare ad usarlo. Adesso \u00e8 ora di vedere il nuovo processo di design in azione. In questa guida, creeremo una feature per un fittizio negozio di arte, completo di demo live e repository GitHub. Seguiteci da casa (o dal vostro cubicolo) e avrete un mockup che imita le interazioni che avrebbe con il server di produzione proprio lato client, senza aver bisogno di dati hard-coded o di workaround temporanei.<\/p>\n","protected":false},"author":818,"featured_media":7000699,"comment_status":"open","ping_status":"open","template":"","categories":[271,91],"tags":[],"coauthors":[391],"class_list":["post-378","article","type-article","status-publish","has-post-thumbnail","hentry","category-javascript","category-numero-74-27-maggio-2013"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/article\/378","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=378"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/media\/7000699"}],"wp:attachment":[{"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/media?parent=378"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/categories?post=378"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/tags?post=378"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/coauthors?post=378"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}