Amintiți-vă când a trebuit să petrecem mult timp optimizând activele proiectului (imagini, CSS, etc ...)? Astăzi, utilizatorii au o conexiune la internet mult mai rapidă și se pare că ne permitem să folosim imagini mai mari sau fișiere flash mai mari, cu multe imagini video și imagini în interior. Cu toate acestea, odată cu creșterea dezvoltării mobile, suntem din nou în aceeași situație. Este extrem de important să creați site-uri bine optimizate, astfel încât să avem aplicații mai rapide, care să descarce mai puțin conținut și să răspundă imediat.
De multe ori folosim aceleași imagini pentru diferite părți ale site-urilor noastre web. De exemplu, într-un magazin online, toate produsele au o imagine de ansamblu. Să presupunem că avem trei pagini în care trebuie să afișăm acele imagini - o pagină pentru listarea produselor, o altă pagină pentru detaliile produsului și oa treia pagină care arată doar imaginea în dimensiunea originală.
Așadar, avem nevoie de trei dimensiuni diferite ale imaginilor și dacă folosim același fișier pentru toate cele trei locuri diferite, atunci browserul va descărca imaginea de dimensiune completă chiar și pentru pagina de înscriere, unde de fapt avem nevoie doar de o imagine de 200x200. Dacă fișierul original este de aproximativ 1MB și avem zece produse pe pagină, atunci utilizatorul va descărca 10MB. Aceasta nu este o idee foarte bună. Dacă puteți, încercați să generați imagini diferite pentru diferitele părți ale site-ului dvs., aceasta va salva o mulțime de KB-uri pentru utilizatorii dvs. Este o idee bună să aveți în vedere rezoluția actuală a ecranului. De exemplu, dacă cineva vă deschide site-ul pe iPhone, nu este nevoie să afișați imaginea antetului gigant, pe care o utilizați în mod normal. Utilizând interogările media CSS, puteți trimite o imagine cu o dimensiune mai mică:
@media numai pe ecran și (min-device-width: 320px) și (max-width-device: 480px) .header background-image: url (... /images/background_400x200.jpg);
Trimiterea unei imagini doar cu dimensiunile corespunzătoare nu este întotdeauna suficientă. Unele formate de fișiere pot fi comprimate foarte mult fără a-și pierde calitatea. Există multe programe care vă pot ajuta. De exemplu, Photoshop oferă o caracteristică frumoasă numită Salvați pentru Web și dispozitive
:
Există o mulțime de opțiuni în acest dialog, dar unul dintre cele mai importante este Calitate
. Setarea la ceva de genul 80% ar putea reduce considerabil dimensiunea fișierului.
Desigur, puteți utiliza codul pentru a comprima fișierele, dar personal prefer Photoshop și îl folosesc ori de câte ori este posibil. Iată un exemplu simplu scris în PHP:
funcția compressImage ($ sursă, $ destinație, $ calitate) $ info = getimagesize ($ source); comutare ($ info ['mime']) caz "imagine / jpeg": $ image = imagecreatefromjpeg ($ source); imagejpeg ($ imagine, $ destinație, $ calitate); pauză; cazul "imagine / gif": $ image = imagecreatefromgif ($ source); imagegif ($ imagine, $ destinație, $ calitate); pauză; cazul "imagine / png": $ image = imagecreatefrompng ($ source); imagepng ($ imagine, $ destinație, $ calitate); pauză; compressImage ('source.png', 'destination.png', 85);
Unul din lucrurile pe care le puteți face pentru a crește performanța aplicației dvs. este reducerea numărului de cereri către server. Deci, fiecare nouă imagine înseamnă o nouă cerere. Este o idee bună să combinați imaginile într-una. Imaginea rezultată este numită a spiriduș
și cu schimbarea background-position
CSS, puteți afișa numai porțiunea imaginii de care aveți nevoie. De exemplu, Twitter Bootstrap folosește sprite pentru pictogramele sale interne:
Apoi, în CSS, poți să faci ceva de genul ăsta, pentru a arăta oricare parte din sprite pe care ți-ar plăcea:
.icon-editare background-image: url ("... /img/glyphicons-halflings-white.png"); pozitie fundal: -96px -72px;
Mecanismul de caching al browser-ului este prietenul tău. Da, uneori în timpul dezvoltării ar putea conduce la unele foarte amuzant
dar vă ajută într-adevăr să îmbunătățiți performanța site-ului. Fiecare browser cache conținut, cum ar fi imagini, JavaScript sau CSS. Există mai multe modalități de a controla cache-ul și vă sugerăm să verificați acest articol minunat pentru o examinare detaliată. În general, puteți controla procesul prin setarea anteturilor, cum ar fi:
$ expire = 60 * 60 * 24 * 1; // secunde, minute, ore, zile antet ("Cache-Control: maxage = i: s ', timpul () + $ expiră)' GMT '); antet ('Last-Modified:' .gmdate ('D, d M Y H: i: s').
HTML5 avansează în fiecare zi. Există o caracteristică frumoasă numită prefetching
care îi spune browserului că va avea nevoie de o resursă în viitorul apropiat și ar trebui să fie descărcat acum, în avans. De exemplu:
Cu câțiva ani în urmă a trebuit să dezvolt o pagină web simplă, care ar fi trebuit să fie doar un fișier HTML. Desigur, au existat câteva imagini, pe care trebuia să le includ. Schemele URI de date mi-au ajutat să rezolv problema. Ideea este să vă transformați imaginile într - un șir de coduri base64 și să le plasați în src
atributul img
etichetă. De exemplu:
Folosind această abordare, imaginea dvs. este de fapt în HTML și salvați o cerere HTTP. Desigur, dacă aveți o imagine mare, șirul va fi foarte lung. Iată un simplu script PHP care convertește imaginile în șiruri de bază:
$ picture = fread ($ fp, dimensiune fisier (fișier $)); fclose ($ fp); // base64 codifică datele binare, apoi sparge-le // în bucăți în funcție de RFC 2045 semantics $ base64 = base64_encode ($ picture); $ tag = '„; $ css = 'url (date: image / jpg; base64,'. str_replace ("\ n", "", $ base64). „;
Puteți găsi acest lucru util în unele cazuri, dar rețineți că nu funcționează foarte bine în IE.
Îmi place să cred că scrierea de CSS este ca scrierea unui cod. Mai trebuie să vă organizați stilurile, să definiți blocuri diferite și relația dintre ele. De aceea cred că managementul CSS este foarte important. Fiecare parte a aplicației trebuie să aibă propriile stiluri și ar trebui să fie bine separate. Păstrarea totul în fișiere diferite oferă o organizare bună, dar, de asemenea, vine cu propriile probleme.
Știm cu toții că utilizarea @import
declarația nu este o idee foarte bună. Asta pentru că fiecare nouă @import
înseamnă o nouă cerere către server. Și dacă aveți, de exemplu, 20 diferite .css
fișiere înseamnă că browser-ul va face 20 de cereri. Și browserul nu redă / afișează pagina înainte de a descărca toate stilurile. Dacă unele dintre dvs. .css
fișierele lipsesc sau sunt foarte mari, veți avea o întârziere mare înainte de a vedea ceva pe ecran.
Proprocesoarele CSS rezolvă toate problemele de mai sus. În continuare vă împărțiți stilurile în fișiere diferite, dar la final, preprocesorul compilează totul într-un singur fișier .css
fişier. Ele oferă de fapt o mulțime de caracteristici reci, cum ar fi variabile, blocuri imbricate, mixins și moștenire. Codul încă arată ca CSS, dar este bine formatat / structurat. Există puține preprocesoare populare care merită verificate - Sass, LESS și Stylus. Iată un exemplu simplu, scris în LESS:
.poziția (@top: 0, @left: 0) position: absolute; sus: @top; stânga: @left; text-aliniere: stânga; font-size: 24px; .cap. .position (20px, 30px); .tipuri .position (10px, -20px); .logo .position (10px, 20px);
va produce
.header position: absolute; top: 20px; stânga: 30px; text-aliniere: stânga; font-size: 24px; .header .tips poziție: absolută; top: 10px; stânga: -20px; text-aliniere: stânga; font-size: 24px; .header .logo poziție: absolut; top: 10px; stânga: 20px; text-aliniere: stânga; font-size: 24px;
Sau, de exemplu, dacă aveți stil pentru un buton și doriți să produceți același buton, dar cu o altă culoare pentru text, puteți face acest lucru:
.butonul border: solid 1px # 000; padding: 10px; fundal: # 9f0; culoare: # 0029FF; butonul activ .button (); culoare: #FFF;
În mod normal, majoritatea dezvoltatorilor nu se gândesc la CSS eficientă. Eficiența CSS reflectă redarea paginii și, dacă stilurile dvs. sunt ineficiente, aplicația va fi redată încet de browsere. Un fapt interesant este că browserele analizează selectorii CSS de la dreapta la stânga. Ceea ce înseamnă că următorul cod:
corpul ul li a culoare: # F000; text-decoration: nici unul;
... nu este deloc eficientă. Acest lucru se datorează faptului că motorul va obține toate tag-uri și va trebui să evalueze fiecare dintre elementele părinte pentru a colecta în cele din urmă stilul necesar. De asemenea, trebuie să știți că, din punct de vedere al eficienței, selectorii se clasifică în ordinea următoare: ID, clasă, etichetă și universal. Acest lucru înseamnă că un element cu un
id
setul va fi redat mai repede decât un element cu doar un selector de etichete. Desigur, nu are sens să adăugați ID-uri pe toate elementele din arborele DOM, dar trebuie să verificați cu siguranță codul și să îl îmbunătățiți acolo unde este posibil. De exemplu, dacă aveți ceva de genul:
ul #navigation li fundal: # ff0232;
Ar trebui să eliminați ul
parte, pentru că aveți doar una #navigare
element pe pagină. Sau în selectorul următor:
corp .content p font-size: 20px;
Este clar că .conţinut
element este un copil al corp
etichetă. Toate elementele sunt de fapt copii ai acestui element.
Iată două linkuri utile pe acest subiect: developers.google.com și css-tricks.com
Așa cum am menționat mai sus, este bine să avem cât mai puțin cod posibil, deoarece browserul nu redă pagina înainte de descărcarea CSS-ului. Iată câteva sfaturi pentru a reduce dimensiunea fișierului.
Combinați stiluri similare:
.header font-size: 24px; .content font-size: 24px;
... se transformă în:
.antet, .content font-size: 24px;
Utilizați stenografi. In loc de:
.header background-color: # 999999; fundal-imagine: url (... /images/header.jpg); pozitie fundal: in partea dreapta sus;
Scrie-o în acest mod:
.header background: # 999 url (... /images/header.jpg) sus;
Reduceți codul CSS. Puteți face acest lucru folosind un instrument care în general elimină toate spațiile și liniile noi. De exemplu, CSSOptimiser sau Minifycss. Este o practică obișnuită de a folosi astfel de instrumente pe partea de server a aplicației, adică ceva scris în limba de back-end. În mod normal, aceste componente minimizează codul și îl servesc utilizatorului.
EtichetăEste o practică bună să includeți dvs. .css
fișiere în cap
tag, în acest fel browserul îl va descărca mai întâi.
La fel ca și în cazul CSS-ului dvs., este bine să reduceți numărul de solicitări trimise către server. În cele mai multe cazuri, încărcarea fișierelor JavaScript nu va opri randarea paginii, dar va face unele porțiuni ale paginii nefuncționale.
Există o mulțime de biblioteci care fac miniaturi JavaScript. Este ceva care va reduce dimensiunea fișierelor, dar rețineți că într-un mediu de dezvoltare este bine să vă păstrați codul curat. Majoritatea acestor instrumente schimbă numele variabilelor dvs. și transformă totul într-un șir dintr-o singură linie, ceea ce face ca procesul de depanare să fie aproape imposibil.
JavaScript nativ nu are un mecanism pentru gestionarea modulelor. Deci, toate aceste lucruri sunt inventate pentru a rezolva această problemă. Ele oferă un API pe care îl puteți utiliza pentru a defini și utiliza modulele. De exemplu, aici este un exemplu preluat de la http://requirejs.org/:
Proiectul meu de probă Proiectul meu de probă
Interior de main.js
, poți să folosești require ()
pentru a încărca orice alte script-uri de care aveți nevoie:
() function (util) // Aceasta functie este numita atunci cand sunt incarcate scripts / helper / util.js. // Daca functia util.js define (), atunci aceasta functie nu este declansata // dependențele utilului au fost încărcate, iar argumentul util va conține // valoarea modulului pentru "helper / util".));
Dacă vorbim despre organizarea codurilor, atunci nu putem să ignorăm partea despre spațiile de nume. Nativ, nu există o astfel de caracteristică în JavaScript, dar puteți obține același lucru cu un mic cod. De exemplu, dacă doriți să vă creați propriul cadru MVC, probabil că veți avea următoarele clase:
var model = functie () ...; var vizualizare = functie () ...; var controler = funcție () ...;
Dacă lăsați lucrurile așa cum sunt în codul de mai sus, atunci acestea devin publice și există șanse mai mari de a crea conflicte cu alte biblioteci din proiectul dvs. Deci, gruparea acestora într-un obiect independent (spațiul de nume) face ca cadrul protejat să fie:
var MyAwesomeFramework = model: function () ..., vizualizare: function () ..., controller: function () ...
Nu este nevoie să reinventăm roata. JavasScript a devenit foarte popular și există multe bune practici acolo. Modelele de design sunt soluții reutilizabile pentru probleme comune în programare. Următoarele dintre ele vă vor ajuta să construiți o aplicație bună. Cu toate acestea, dacă încerc să le acoperez pe toate aici, va trebui să scriu o carte, așa că sunt doar câteva dintre ele:
Utilizați acest model pentru a crea o instanță a unui anumit tip de obiect. Iată un exemplu:
var Class = funcție (param1, param2) this.var1 = param1; this.var2 = param2; Class.prototype = method: function () alert (this.var1 + "/" + this.var2); ;
Sau puteți încerca acest lucru:
funcția Clasă (param1, param2) this.var1 = param1; this.var2 = param2; this.method = funcția () alertă (param1 + "/" + param2); ; ; var instanță = clasă nouă ("valoare1", "valoare2");
Modelul de module ne dă posibilitatea de a crea metode private și publice. De exemplu, în codul de mai jos, variabila _index
și metoda privateMethod
sunt private. creştere
și getIndex
sunt publice.
var () var _index = 0; var privatMethod = function () return _index * 10; retur increment: function () _index + = 1;; ;) ();
Ori de câte ori vedeți abonarea sau expedierea evenimentelor, probabil veți vedea acest model. Există observatori care sunt interesați de ceva legat de un anumit obiect. Odată ce acțiunea are loc, obiectul îi anunță pe observatori. Exemplul de mai jos arată modul în care putem adăuga un observator la Utilizatori
obiect:
var Utilizatori = list: [], ascultători: , adăugați: funcția (nume) this.list.push (name: name); this.dispatch ( "user-adăugată"); , pe: funcția (eventName, ascultător) if (! this.listeners [eventName]) this.listeners [eventName] = []; this.listeners [EVENTNAME] .push (ascultător); , expediere: funcție (eventName) if (this.listeners [eventName]) pentru (var i = 0; iFuncționarea lanțului de funcții
Acest model este o modalitate frumoasă de a organiza interfața publică a modulului dvs. Economiseste timp si imbunatateste lizibilitatea:
var Utilizator = profil: , nume: funcție (valoare) this.profile.name = valoare; returnați acest lucru; , funcția: funcție (valoare) this.profile.job = value; returnați acest lucru; , getProfile: funcția () return this.profile; ; var profil = user.name ("Krasimir Tsonev") job ("dezvoltator web") getProfile (); console.log (profil);Vă recomandăm insistent să citiți această carte de Addy Osmani. Este una dintre cele mai bune resurse pe care le puteți găsi despre modelele de design în JavaScript.
Active-Pack
Acum că ne apropiem de sfârșitul acestui articol, vreau să împărtășesc câteva idei despre gestionarea codurilor CSS și JavaScript pe server. Este o tehnică foarte frecventă de a adăuga îmbinarea, minificarea și compilarea în logica aplicației. Deseori există un fel de mecanism de cache, dar toate lucrurile se întâmplă în timpul runtime-ului. Deci, probabil, aveți o anumită logică a codului, care gestionează cererea
.js
sau.css
fișiere și servește conținutul corespunzător. În spatele acestui proces este compilația, minificarea sau orice folosiți pentru a vă împacheta activele.În ultimele mele proiecte am folosit un instrument numit
Active-pack
. Este foarte util și voi explica în detaliu ce anume face, dar partea mai interesantă este modul în care am folosit-o. Această bibliotecă este destinată să fie utilizată numai în modul de dezvoltare, nu este ceva care rămâne în codul dvs. de bază și nu este ceva pe care ar trebui să-l implementați pe serverul de producție.Ideea este de a utiliza ambalatorul numai în timp ce lucrați la active (CSS, JS). De fapt, ea urmărește modificările în directoarele specifice și compilează / împachetează codul într-un singur fișier. Folosind această abordare, nu trebuie să vă gândiți la minificare sau compilație. Tot ce trebuie să faceți este să trimiteți fișierul static compilat utilizatorului. Aceasta sporește performanța aplicației, deoarece servește doar fișiere statice și, desigur, simplifică lucrurile. Nu este nevoie să setați nimic pe serverul dvs. sau să implementați o logică inutilă.
Iată cum puteți configura și utiliza
Active-pack
.Instalare
Acest instrument este un modul Nodejs, deci trebuie să aveți Nod deja instalat. Dacă nu, mergeți la nodejs.org/download și luați pachetul pentru sistemul dvs. de operare. Dupa aceea:
npm instalează -g assetspackfolosire
Modulul funcționează cu configurația JSON. Când este utilizat prin linia de comandă, ar trebui să plasați setările într-un a
.JSON
fişier.Prin linia de comandă
Creaza un
assets.json
fișier și executați următoarea comandă în același director:assetspackDacă fișierul dvs. de configurare folosește un alt nume sau se află într-un alt director, utilizați:
assetspack --config [calea catre fisierul json]În Cod
var AssetsPack = necesită ("assetpack"); var config = [tip: "css", ceas: ["css / src"], ieșire: "tests / packed / styles.css", minify: true, exclude: ["custom.css"]]; var pack = nou AssetsPack (config, function () console.log ("AssetsPack se uită");); pack.onPack (funcția () console.log ("AssetsPack a făcut lucrarea"););configurație
Configurația ar trebui să fie un fișier / obiect JSON valid. Este doar o serie de obiecte:
[(obiect de bunuri), (obiect activ), (obiect bun), ...]Obiectul activelor
Structura de bază a obiectului de bunuri este astfel:
tip: (tip de fișier / șir, ar putea fi css, js sau mai puțin de exemplu), urmăriți: (director sau directoare pentru vizionare / șir sau matrice de șiruri de caractere /), pack: (director sau directoare pentru ambalare / șiruri /.), ieșire: (cale către fișierul de ieșire / șir /), minify: / boolean /, exclude: (matricea de nume de fișiere)
ambalaj
proprietatea nu este obligatorie. Dacă o pierdeți, atunci valoarea sa este egală cuceas
.minify
în mod implicit, este falsă.Iată câteva exemple:
Ambalarea CSS
type: "css", ceas: ["tests / data / css", "tests / data / css2"], teste / packed / styles.css ", minify: true, exclude: [" header.css "]Ambalarea JavaScript
tip: "js", ceas: "test / data / js", pachet: ["tests / data / js"], output: "tests / packed / scripts.js", minify: true, exclude: .js "]Ambalare
.Mai puțin
FișiereAmbalajul
.Mai puțin
fișierele sunt puțin diferite.ambalaj
proprietatea este obligatorie și este, practic, punctul de intrare. Ar trebui să importați toate celelalte.Mai puțin
acolo.exclude
proprietatea nu este disponibilă aici.tip: "mai puțin", urmăriți: ["teste / date / mai puțin"], pachet: "test / data / less / index.less", ieșire: "tests / packed / styles-less.css"Dacă întâmpinați probleme, vă rugăm să verificați
teste / ambalare-less.spec.js
a depozitului în GitHub.Ambalarea altor formate de fișiere
Active-pack
funcționează cu orice format de fișier. De exemplu, putem combina șabloanele HTML într-un singur fișier, făcând astfel ceva:tip: "html", urmăriți: ["tests / data / tpl"], ieșire: "tests / packed / template.html", exclude: ["admin.html"Singurul lucru pe care trebuie să-l cunoașteți aici este că nu există nicio minificare.
Concluzie
Ca dezvoltatori web pentru front-end, ar trebui să încercăm să oferim cea mai bună performanță posibilă pentru utilizatorii noștri. Sfaturile de mai sus nu ar trebui să acopere toate aspectele legate de organizarea și performanța activelor, dar ele sunt cele pe care le-am tratat personal în timpul activității mele zilnice. Vă rugăm să nu ezitați să împărtășiți câteva dintre sfaturile de mai jos, în comentarii.