VândPupăză

Icon

Bine o zis cine o zis cand o zis ce o zis

Scuipa mai putin JavaScript cu dynamic script loading

Atentie: acest post este lung si geek-oriented. Daca te plictisesti treci repede la pisica

Am gasit pe Ajaxian “Split the initial payload” – un articol care discuta despre cantitatea de JS care se arunca in pagina la incarcare si cum afecteaza aceasta performanta interfetei.

Sunt sigur ca nu ti se pare normal sa incarci in pagina mai mult JS decat ai nevoie. E bun simt!
Dar incarci mai mult cod decat ai nevoie. Nu-i asa?

Ni se intampla tuturor si nu o facem cu rea intentie. De obicei timpul ne preseaza sau pur si simplu ideea nu sare. Daca nu incerci sa-ti privesti aplicatia in ansamblu ai sa scapi codul de sub control. Asta nu se refera doar la complexitate ci si la dimensiunea fisierului ce va fi incarcat.

Pe masura ce aplicatiile web de azi devin din ce in ce mai complexe si cantitatea de cod aruncata in ele este considerabil mai mare. Mai mult ca sigur nu ai nevoie de tot codul la prima incarcare.

E un truc inteligent sa iti imparti codul ce tine de front-end in bucati pe care le incarci on demand sau asincron in fundal. Desigur e un joc mai complicat odata ce depinzi de incarcarea fisierelor externe. Totusi, prin decizii rationale poti spori performanta aplicatiei tale incarcand in liniste tot ceea ce nu este vital pentru prima rulare.

Dynamic Script Loading

Un fisier JavaScript se poate incarca in pagina prin generarea unui element DOM de tip script caruia ii atribui proprietatea src care indica spre fisierul ce va fi incarcat. Nu uita sa mentionezi tipul fisierului pentru ca browserul sa interpreteze corect datele incarcate.

var script = document.createElement('script');
script.type= "text/javascript";
script.src="path/to/javascript.js" mce_src="path/to/javascript.js"             ;

document.getElementsByTagName('head')[0].appendChild(script);

Ultima linie atribuie elementului head scriptul si face toata magia posibila. Nu e obligatorie incarcarea fisierului in head dar e o buna practica sa faci acest lucru.
Problema intervine atunci cand trebuie sa interactionezi cu datele din fisierul incarcat dinamic.

Pentru ca incarcarea se va face asincron poti avea surpriza ca o functie care foloseste datele din fisierul in cauza sa se declanseze inainte ca fisierul sa se fi incarcat complet. Asta rezulta intr-o eroare urata si probabil functionalitate distrusa.

In Internet Explorer te poti lega de proprietatea onreadystatechange, similar cu apelarea AJAX, si apoi folosesti un event handler bazat pe readystate. Tipurile de raspuns pe care le poti primi de la IE sunt

  • uninitialized
  • loading
  • loaded
  • interactive
  • complete

Mofturi IE
Internet Explorer 7 e imprevizibil in tipul de readystate pe care il returneaza dupa ce codul s-a incarcat. Uneori poti primi ‘completed’ sau ‘loaded’ in cazul in care operatiunea s-a terminat ok. Sa ai grija sa asculti pentru ambele raspunsuri.

script.onreadystatechange= function () {
if (script.readyState == 'complete' || script.readyState == 'loaded'){
//code here
}
}

Firefox, Safari si orice alt browser care are la baza Geko sau Webkit pot folsi onload. Te poti lega cu aceasta de fisierul pe care il vei incarca si poti rula metode care interactioneaza cu fisierul proaspat incarcat.

script.onload=function(){
//code here
}

In exemplele de mai sus am folosit functii anonime pentru a incapsula codul ce va fi executat cu fisierul incarcat. Desigur ca poti atribui nume de functii deja existente.

O resursa care m-a ajutat mult sa inteleg si sa folosesc metoda asta e JavaScript Madness.
Iti recomand sa citesti articolul de acolo pentru detalii suplimentare la cum e tratat dynamic script loading in diferite browsere.

Avantaje

  • Mai putin cod la incarcarea paginii rezulta in performante mai bune pentru aplicatie
  • Metoda merge si pentru alte tipuri de fisiere (ex: css) desi nu vad o utilitate rezonabila a acestei metode. Daca trebuie sa incarci dinamic fisiere .css poate e cazul sa-ti regandesti structura stilurilor.Totusi, ai putea incarca in fundal fisiere .css (preloading) pentru paginile pe care presupui ca le va accesa vizitatorul. Din nou, depinde mult de arhitectura aplicatiei tale.

Dezavantaje

  • Metoda e suficient de ‘obtrusive’ incat sa nu iti doresti atasarea evenimentelor critice pentru aplicatie de incarcarea unui script extern. Conexiunile se inneaca, fisierele se modifica, intra in cache (neasteptat) sau iti servesc raspunsuri neasteptate.Daca o bucata de cod este critica pentru functionarea aplicatiei pune-o intr-un fisier care se incarca prin metoda clasica: odata cu pagina. (de fapt nu e chiar odata dar o lasam asa de dragul simplitatii)
  • JavaScript Madness sustine ca scriptul incarcat in felul acesta nu poate face call-uri de tip POST. Merge doar GET. Eu nu am avut problema asta. Ce-i drept, in implementarea pe care am facut-o am folosit si un PROXY in SWF prin care rutam apelurile. (Cross Domain AJAX intr-un post viitor)

Category: JavaScript, Web, Work

Tagged:

2 Responses

  1. Răzvan says:

    O metoda compacta care face acelasi lucru de la Thomas Frank: http://www.thomasfrank.se/easier_than_ajax.html

  2. vladootz says:

    foarte fain si interesant, dar scrie `urile putin mai mari ca nu prea se vede codul din post…

Leave a Reply