Forzare il caching del javascript

Tuesday, 17 July 07
Il motivo principale per cui non scrivo spesso sul blog in questi giorni non e' l'abitudine consolidata del bagno a mare ogni pomeriggio: a dire il vero questo aumenta la mia produttivita'. Il vero motivo e' che dopo aver realizzato la struttura principale del framework Ruby che utilizziamo assieme a Fabio, mi sono messo a testarlo, e in realta' sono finito per scrivere una applicazione, che siccome sembra anche utile, presto sara' online ad uso e consumo di chi volesse divertirsi: si tratta di un programma di todo list che pone l'accento sulla condivisione delle cose da fare con amici, colleghi, ed altre persone con cui si portano avanti delle attivita' assieme.

Oggi notavo che nonostante i miei sforzi di tuning, il codice HTML veramente semplice e tutto il resto, in realta' l'applicazione non era cosi' veloce come pensavo dovesse essere: ho scelto di utilizzare javascript/ajax al minimo (funziona anche disabilitandolo in realta'), per cui il tempo di refresh e' vitale.

E' bastato controllare i log del web server mentre provavo ad usare l'applicazione per capire qual'era il problema. Ad ogni pageview per qualche ragione l'applicazione stava caricando il javascript, ogni volta. Forse perche' il javascript e' in realta' servito al browser tramite un file PHP che fa l'include di tutti i file javascript reali (l'applicazione e' scritta in Ruby, PHP viene usato come una sorta di server side includes per il javascript). Insomma il web server non sparava i giusti header per permettere il caching, e questo distruggeva completamente le prestazioni, dal mio punto di vista: il refresh era sempre sotto il secondo, ma non una scheggia come avrebbe dovuto essere.

Per fortuna e' bastato aggiungere questo:
header("Content-type: text/javascript");
header("Cache-Control: max-age=200000000");
header("Expires: Fri, 14 Jul 2017 22:26:24 GMT");
E ora e' una scheggia, proprio come me lo immaginavo :)
5516 views*
Posted at 21:57:53 | permalink | 13 comments | print
Do you like this article?
Subscribe to the RSS feed of this blog or use the newsletter service in order to receive a notification every time there is something of new to read here.

Note: you'll not see this box again if you are a usual reader.

Comments

napyfab writes:
18 Jul 07, 02:35:02
Bene bene.. A quando il lancio? ;)
TixXio writes:
18 Jul 07, 03:15:14
Ho risolto la settimana scorsa lo stesso problema :D
Fabrizio writes:
18 Jul 07, 03:26:57
Io ho utilizzato un sistema di caching dei file javascript comuni a tutte le pagine aggiungendo anche il comando ETag.

Out of topic: Scusate stavo pensando di implementare un sistema per il login accentrato su diversi siti. Qualcuno di voi utilizza session save handler personalizzati su DB?

Grazie
Fabrizio
antirez writes:
18 Jul 07, 06:00:08
@napyfab: non so bene, a giorni. Gia' e' online a dire la verita' (tudulist.com), ma ancora chiuso, lo stiamo usando in 10 persone.

In realta' la cosa bella e' che non c'e' alcuna pressione perche' il tutto e' nato come gioco, e dopo e' divenata una cosa utile internamente, dunque la voglia di condividere non e' per business in questa fase (e probabilmente per sempre), ma giusto perche' visto che ormai c'e' e stiamo iniziando ad usarlo un po' di persone mi piace l'idea che la community aumenti.

In realta' il vantaggio nello sviluppo c'e' in ogni caso perche' lo stesso codice sara' usato per gli altri nuovi servizi che vengono sviluppati in seno a Merzia.
antirez writes:
18 Jul 07, 06:02:31
@Fabrizio: uso sempre le sessioni sul DB per il login. Ogni tabella user ha un campo 'secret' che e' un numero pseudocasuale a 256 bit ottenuto da /dev/urandom. Ad ogni logout tale numero viene modificato. Il cookie include anche l'ID utente cosi' fare la query e' piu' veloce.

Se vuoi aumentare le prestazioni e non ti interessa cambiare il secret al momento del logout (ma e' interessante sloggare tutti gli altri con lo stesso account per ragioni di sicurezza), puoi mettere nel cookie un HMAC ed evitare la query sul DB.
Doxaliber writes:
18 Jul 07, 12:05:44
Può essere davvero utile un'applicazione "semplice" di questo genere... :-)

PS Io il bagno a mare di solito lo faccio prima di pranzo, tipo dalle 12:30 alle 14:00, sono gli orari peggiori ma l'intero pomeriggio in questo momento per me è vitale.. :-D
straluna writes:
19 Jul 07, 05:52:16
ciao!
Anche io mi sono messo da un po' a guardare ruby e mi piace assai [*].
Ricordo che nei tuoi vecchi post dicevi che Merzia come filosofia non avrebbe usato RoR ma un suo framework e mi pare che sia anche quello che è successo per tudulist, giusto?
Altra domanda da niubbo: perchè preferisci usare eruby con mod_ruby e non come cgi?
Io intanto mi metto in lista per un account di tudulist.

ciao,
a.
[*] epperò "L'espressivita' del C" effettivamente...
antirez writes:
19 Jul 07, 06:33:26
@straluna: Ciao :)
Ruby ha alcune cose che non mi piacciono e vorrei diverse, ma non c'e' dubbio che programmare in Ruby e' divertente e che il linguaggio e' flessibile. Non lo avevo mai usato per nulla di serio fino ad alcune settimane fa e ora mi sento abbastanza "fluente", una sensazione che non ho con Python ad esempio. Insomma mi sono divertito un bel po' :)

Infatti come dici per tudulist abbiamo fatto un nostro framework (a dire la verita' il framework l'abbiamo fatto per un'altra applicazione che stiamo scrivendo, tudulist e' una cosa mia personale che e' nata come effetto collaterale del testing del framework).

Il framework e' composto dalle seguenti parti:

db.rb che e' in pratica una versione ridotta di Active Records che non ha bisogno di generare niente quando cambiano le tabelle, e' tutto a runtime, e che e' diverse volte piu' veloce e meno completo di Active Records. Tuttavia fa un sacco di cose comode. Ad esempio:

user = fetch("SELECT * FROM user WHERE id=1")
user['username'] = "pippo"
user.save

e come AR fa automaticamente l'update.

C'e' anche user.delete per fare il delete, queste
cose funzionano a patto che la tabella abbia un
campo 'id' unico auto incrementale.

Per iterare tra i risultati invece:

users = fetchall("SELECT * FROM users")
users.each {|row| .... }

altrimenti si puo' accedere come un array,
user[0], user[1], e la libreria prendera'
i record in maniera "lazy", man mano che servono
continuera' a a chidere risultati a MySQL.

Gestione dell'auto escape:

foo = fetch("SELECT * FROM foo WHERE name=",name,"AND surname=",surname)

name e surname saranno passati da mysqlescape prima di essere utilizzati nella query.

L'inserimento e' semplicemente questo:

row = {
:table => 'foo',
"name" => "Salvatore",
"surname" => "Sanfilippo"
}
insert(row)

piu' o meno e tutta qui. E' chiaro che abbiamo scelto di non seguire la strada di automatizzazione delle select, diventa line noise scrivere :cond ... :id ... secondo la mia personale opinione, tanto vale vedere la query e non dover utilizzare un diverso linguaggio che non e' SQL ma che non e' piu' potente o astratto di SQL.

Oltre a questo il framework gestisce la generazione di HTML. La lib CGI che usiamo con mod_ruby era troppo lenta a generare l'HTML cosi' ho scritto una piccola classe HTMLGen che usa method_missing per fare tutto. La libreria aggiunge anche il concetto di "virtual tag", per cui posso scrivere ad esempio

H.b {"Nome? "+H.checkbox("name"=>"foo")}

checkbox e' un tag virtuale definito da questa
linea di codice:

"checkbox" => {"tag"=>"input","type"=>"checkbox","class"=>"inputcheckbox"},

Facile no?
Poi c'e' la gestione della generazione della pagina, degli errori a runtime, dei campi mancanti, e tante altre cose che non e' il caso ripetere ogni volta.

In totale sono meno di 400 linee di codice che pero' fanno tutto quello che a noi serve, mi rendo conto che per alcuni cio' possa essere incredibilmente primitivo come framework.

Per quanto riguarda l'account su tudulist, apro tra meno di 15 giorni, ma comunque posto una nota nel blog :) Ciao!
antirez writes:
19 Jul 07, 06:49:32
Dimenticavo: sul perche' mod_ruby e non CGI: e' piu' veloce e condivide l'interprete tra le sessioni che e' un male ma anche un grande vantaggio per certi tipi di caching, persistenza delle connessioni al DB, e cosi' via.
'u cummisaru writes:
19 Jul 07, 12:30:42
Solitamente quando leggo questo blog non riesco a comprendere immediatamente il senso del discorso: è una mia mancanza, che prontamente colmo con una rapida ricerca su Google dei termini più ostili..
..ma spesso queste mie ricerche si dilungano troppo e non mi aiutano a comprendere realmente (che per me vuol dire poter sperimentare di persona) il problema e la soluzione postati. Per esempio, quando dici:
<CODE>E' bastato controllare i log del web server mentre provavo ad usare l'applicazione per capire qual'era il problema.</CODE> mi chiedo se è possibile anche per me prendere visione di questi log? Cioè, come si fa?? E' una di quelle cose basilari ma che l'università da per scontata e nessuno ci insegna! Non ho mai visto un log, non so immaginarmelo; io ho un sito ospitato su altervista: c'è un modo per toccare con mano queste informazioni?? Grazie
antirez writes:
20 Jul 07, 10:12:31
Be allora basta che vai a mare a Marina di Ragusa zona "dogana" che sono sempre li e ne parliamo ;)
'u cummisaru writes:
20 Jul 07, 10:19:54
vabbo'.. appena mi do "Laboratorio di Calcolatori Elettronici" (a fine mese) scendo. Io sto a Torre di Mezzo quindi è probabile che ci incontriamo al Piper (anche se ogni anno dà meno soddisfazioni dell'estate precedente) ;)
'u cummisaru writes:
20 Jul 07, 10:45:46
NON SONO RIUSCITO AD EDITARE IL MIO COMMENTO, mi ero scordato una cosa da chiederti:
la zona 'dogana' dove si trova? Io conosco la 'Gesuiti' perchè mi ci hanno fatto una multa, poi la 'lungomare nuova' e 'lungomare vecchia', ma questa dogana non riesco nemmeno ad immaginarmela.

P.S: sono rimasto scioccato un mesetto fa quando al posto della creperia + buona del mondo vi ho trovato un negozio di ottica, lì nella piazza della palla-a-canestro.. finisce un'epoca: l'altra creperia che è rimasta non saprà mai soddisfarmi! :(
Quella che dico io era uno spettacolo mangiarci, e se non ti piacciono le crepes ci andavi lo stesso per distruggerti dalle risate nel vedere i due gestori che non la finivano mai di litigare e urlarsi contro di tutto, anche alle 4 del mattino! :D
comments closed