Optimering af Javascript og CSS

Jeg er forholdsvis flitting bruger af bookmark servicen Delicious.com, og det hænder da også at jeg rent faktisk kommer tilbage til nogle af de links jeg er faldet over i løbet af tiden … i dag var sådan en dag, og emnet handler om en måde hvorpå man kan optimere sin sides brug af Javascript og CSS. Følgende post kræver en stor tak og 100% kredit til Niels Leenheer.

Flere filer = flere requests = ventetid = :(

Jeg synes at støde ind i dette scenarie mere og mere på det sidste, og som billederne herunder viser, skal grunden meget ofte findes i brugen af JQuery og ikke mindst plugins dertil.

Følgende eksempel screenshots er alle taget fra en lokal version af sitet www.usgreencardoffice.com, som er et projekt jeg har været en del af gennem det sidste års tid. Som det ses benytter vi en del forskellige JQuery plugins (hvilket, som sagt ikke længere er unormalt), men fordelen ved at kunne hente og lave disse enekltstående plugins så let, kan hurigt gå hen og blive en ulempe, eller i hvert fald mindre fordelagtigt.

På et tidspunkt, vil man komme op på så mange filer, at ens browser ikke længere kan hente dem alle på én gang, hvorfor den besøgende bliver nød til at hente dem lidt efter lidt, for endelig at kunne se resultatet — Ventetid!

Følgende screenshots er alle taget efter at have tømt min browsers cache (hvilket undre mig lidt, at Firebug stadig siger 22.3 KB from cache?!), og er altså resultater ved første besøge på sitet.

Javascripts (172.9 KB — 2.32 sek.)

CSS (10.9 KB — 637 msek.)

Optimering

Tricket til at komme ovenstående til livs, er faktisk rimelig simpelt, men kan gøres på flere planer. Flere og flere plugins (foruden JQuery biblioteket selv), kommer i en “minifyed” version, som jeg klart vil anbefale at benytte i produktion frem for den “originale kildekode”. Med “minifyed” forståes at alle funktioner og deklerationer er “rykket sammen” (variabler kan forkortes m.m.) på én laaaang linie, samt at alt whitespace er fjernet for at mindske filstørrelsen — og der kan hutigt sparres en del KB allerede der!

Næste skridt vi kan tage, og det er hele tricket ved dette, er at kombinerer de mange filer til én. Der findes flere måder at gøre dette på, bl.a. " Googles Closure Compiler". En bonus ved Closure Compiler er at denne også udfører “minifying” af den endelige kombinerede Javascript fil. En ulempe, i min optik, er at dette ellers fantastiske værktøj, kræver at man manuelt skal compile alle sine Javascripts efter redigering, via en terminal — det er selvfølgelig til at overleve, men kunne jeg blive fri, valgte jeg helst det… og det kan jeg :)

Og det er netop dérfor jeg er så glad for denne metode, Niels har præsenteret mig for her i weekenden, da den vha. lidt URL-rewriting gør hele optimerings-processen automatisk! Ydermere er denne løsning designet til at kunne genererer cache-version af dine kombinerede filer, hvorefter der næsten ingen “overhead” er tilbage.

Kombinering af filer

Ideen er, at du på din server har én mappe til CSS og én mappe til Javascripts. Vha. følgende .htaccess-regl, kan vi fortælle vores script (combine.php), at dette skal kombinerer en “kæde” af filer til én:

RewriteEngine On
RewriteBase /
RewriteRule ^css/(.*\.css) /combine.php?type=css&files=$1
RewriteRule ^javascript/(.*\.js) /combine.php?type=javascript&files=$1

I vores -sektion, hvor vi normalt ville have en masse links som dette:

<link rel="stylesheet" type="text/css" href="http://www.usgreencardoffice.com/css/ui.core.css," />
<link rel="stylesheet" type="text/css" href="http://www.usgreencardoffice.com/css/ui.dialog.css" />
<link rel="stylesheet" type="text/css" href="http://www.usgreencardoffice.com/css/ui.theme.css" />
<link rel="stylesheet" type="text/css" href="http://www.usgreencardoffice.com/css/prettyPhoto.css" />
<link rel="stylesheet" type="text/css" href="http://www.usgreencardoffice.com/css/jquery.Jcrop.css" />
<link rel="stylesheet" type="text/css" href="http://www.usgreencardoffice.com/css/style.css" />

kan vi nu nøjes med at linke dem komma-separeret, som her:

<link rel="stylesheet" type="text/css" href="http://www.usgreencardoffice.com/css/ui.core.css,ui.dialog.css,ui.theme.css,prettyPhoto.css,jquery.Jcrop.css,style.css" />

Det samme trick gør sig selvfølgelig gældende for Javascript-filerne. For at få løsningen til at fungerer helt optimalt, skal du oprette en skrivbar mappe kaldet “cache”.

Resultatet

Screenshots er igen alle taget efter at have tømt min browsers cache, svarende til at besøge sitet for første gang — Dvs. at du højst sansynligt vil spare endnu mere trafik ved andet besøg, da caching herefter vil træde i kræft :)

Javascripts (156.3 KB — 1.48 sek.)

CSS (8.8 KB — 10 msek.)

Download

Download combine.php.

Mere om minifying — forbedringer

Efter at have implementeret ovenstående, og set nærmere på nogle af de plugins jeg benytter (samt de scripts jeg selv har måtte tilføje), tænkte jeg at det ville være interessant at udvide løsningen med automatisk “minifying”. Dette er stadig en “todo” for mig, men måske du har samme tanker? I så fald vil følgende link måske have interesse: http://github.com/rgrove/jsmin-php/blob/master/jsmin.php