18 iunie 2020 9 min citit 2534

reducerea

Chiar dacă avem astăzi computere și dispozitive mobile mai rapide, noi ca dezvoltatori ar trebui să ne gândim la publicul pentru care construim produsul în ansamblu. Nu toată lumea are acces la același tip de dispozitiv rapid sau se află pe cea mai rapidă rețea de internet. Deci, trebuie să aruncăm o privire mai largă asupra problemelor de performanță. Performanța poate fi urmărită în multe moduri diferite, dar pentru acest articol, ne vom concentra pe performanța frontend. Privim mai atent acest aspect și oferim sugestii pentru posibile îmbunătățiri în acest domeniu.

Performanță frontend

Optimizarea performanței frontendului este esențială, deoarece reprezintă aproximativ 80-90% din timpul de răspuns al utilizatorilor. Deci, atunci când un utilizator așteaptă încărcarea unei pagini, aproximativ 80-90% din timp se datorează codului și activelor legate de frontend. Ilustrațiile de mai jos arată raportul dintre activele frontend/backend care trebuie încărcate pentru LinkedIn.

Sursa: http://www.stevesouders.com/

O mare parte din timpul de încărcare al frontend-ului este cheltuit pentru executarea fișierelor JavaScript, precum și pentru redarea paginii. Dar o parte critică pentru îmbunătățirea performanței frontendului este reducerea dimensiunii pachetului JavaScript care ar trebui descărcată prin rețea. Cu cât este mai mică dimensiunea pachetului JavaScript, cu atât pagina poate fi mai rapidă disponibilă pentru utilizatori.

Dacă ne uităm la datele istorice, putem vedea că fișierele JavaScript au fost în medie de 2 KB în 2010. Dar odată cu evoluția JavaScript, introducerea de noi biblioteci JavaScript, precum Angular sau React, și cu conceptul de aplicații cu o singură pagină dimensiunea medie a activelor JavaScript a crescut la 357 KB în 2016. Trebuie să folosim aceste noi tehnologii pentru soluții mai bune. Dar trebuie, de asemenea, să luăm în considerare modalitățile posibile de a le îmbunătăți performanța, făcând lucruri precum reducerea dimensiunii globale a pachetului JavaScript. Dar, înainte de a ne arunca cu privire la acest subiect, trebuie să ne familiarizăm cu pachetele JavaScript. Ce sunt exact?

Pachete JavaScript

Aplicația dvs. frontend are nevoie de o grămadă de fișiere JavaScript pentru a rula. Aceste fișiere pot fi în formatul dependenței interne, cum ar fi fișierele JavaScript pe care le-ați scris dumneavoastră. Ele pot fi, de asemenea, dependențe externe și biblioteci pe care le utilizați pentru a vă crea aplicația, cum ar fi React, lodash sau jQuery. Deci, pentru ca pagina dvs. să se încarce prima dată, aceste fișiere JavaScript trebuie să fie accesibile aplicației. Deci, cum le expunem?

În trecut, modul de expunere a fișierelor JavaScript era mult mai simplu. Majoritatea paginilor web nu au nevoie de multe active JavaScript. Deoarece nu aveam acces la un mod standard de solicitare a dependențelor, a trebuit să ne bazăm pe utilizarea dependențelor globale. Imaginați-vă că aveam nevoie atât de jQuery, cât și de main.js și other.js care dețin toate aplicațiile noastre logice JavaScript. Modul în care am putut expune aceste dependențe arăta cam așa:

Aceasta a fost o soluție ușoară la această problemă, dar a scăpat rapid de sub control atunci când a scalat aplicația. De exemplu, dacă main.js se schimbă într-un mod care depinde de codul din other.js, trebuie să reordonăm etichetele scriptului nostru astfel:

După cum putem vedea, gestionarea unei astfel de structuri de cod la scară ar deveni rapid o mizerie. Dar după un timp, au existat soluții mai bune pentru gestionarea acestui lucru în aplicații. De exemplu, dacă utilizați NodeJS, v-ați putea baza pe sistemul de module propriu al NodeJS (bazat pe specificațiile commonJS). Acest lucru vă va permite să utilizați funcția de solicitare pentru a solicita dependențe. Deci, într-un mediu Node, fragmentul de cod de mai sus ar arăta cam așa:

În prezent, nu aveți doar câteva fișiere JavaScript pentru a vă rula aplicația. Dependențele JavaScript pentru aplicația dvs. pot include câteva sute sau mii de fișiere și este clar să le enumerați, așa cum fragmentul de mai sus nu este posibil. Există mai multe motive pentru aceasta:

  • Separarea activelor JavaScript în fișiere separate necesită o mulțime de solicitări HTTP atunci când diferite părți ale aplicației necesită dependențe diferite. Nu va fi performant și durează mult timp
  • În plus, NodeJS require este sincron, dar vrem să fie asincron și să nu blocheze firul principal dacă activul nu este deja descărcat

Deci, cea mai bună abordare pare să fie plasarea întregului cod JavaScript într-un singur fișier JavaScript și gestionarea tuturor dependențelor din acesta. Ei bine, aceasta este sarcina de bază a unui pachet JavaScript. Deși diferiți grupatori pot avea strategii diferite pentru a face acest lucru. Să explorăm acest lucru un pic mai departe și să vedem cum realizează acest lucru un pachet. Apoi vom vedea dacă există îmbunătățiri suplimentare pe care le putem face pentru a obține o dimensiune mai mică a pachetului și, prin urmare, mai multă performanță. În scopul acestui articol, vom folosi Webpack ca pachet, care este una dintre cele mai faimoase opțiuni de acolo.

Am făcut o demonstrație personalizată pentru .
Nu chiar. Faceți clic aici pentru a o verifica .

Construirea unui pachet de probe cu Webpack

Să începem prin configurarea unui proiect Webpack simplu. Vom folosi pachetele de bază pentru lansarea unui proiect simplu de aplicație web. React, ReactDOM ca cadru UI, SWC ca alternativă mai rapidă la Babel pentru transpilare, precum și o serie de instrumente și încărcătoare Webpack. Așa va arăta package.json:

De asemenea, vom avea nevoie de un webpack.config.js, care este punctul de intrare de configurare pentru comenzile noastre Webpack. Există mai multe opțiuni în acest fișier, dar să clarificăm câteva dintre cele importante:

  • mod - Aceasta este o opțiune pentru Webpack pentru a ști dacă ar trebui să facă orice optimizare, pe baza opțiunii către care este transmisă. Vom discuta în continuare mai târziu
  • ieșire - Această opțiune spune Webpack unde ar trebui să încarce sau să pună pachetele asamblate la nivel rădăcină. Este necesar atât calea, cât și numele fișierului
  • HTMLWebpackPlugin - Această opțiune ne ajută să facilităm difuzarea fișierelor noastre HTML cu pachetul Webpack
  • încărcătoare - Aceste suplimente pentru încărcător vă ajută să transformați majoritatea caracteristicilor moderne ale limbajului de codare în cod de înțeles pentru toate browserele

Măsurarea și analiza

Acum, este timpul să obținem câteva măsurători inițiale pentru construcția noastră Webpack. Când Webpack realizează compilarea, avem nevoie de un fel de statistici cu privire la modulele construite, viteza de compilare și graficul de dependență generat. Webpack ne oferă deja instrumentele pentru a obține aceste statistici, executând o comandă simplă CLI:

Prin trecerea --json> compilation-stats.json, îi spunem Webpack să genereze statisticile de construire și graficul de dependență ca un fișier json cu numele nostru specificat. Trecând steagul --profile, obținem statistici de construcție mai detaliate pe module individuale. După executarea acestei comenzi, primiți un fișier json, care include o mulțime de informații utile. Dar pentru a face lucrurile mai ușoare, vom folosi un instrument recomandat care va vizualiza toate aceste statistici de construcție. Tot ce trebuie să faceți este să trageți compilation-stats.json în secțiunea specificată în acest instrument oficial de analiză. După ce facem acest lucru, obținem următoarele rezultate.

Analiza Webpack

Obținem următorul tabel cu informații generale despre analiza compilării Webpack:

Versiunea Webpack utilizată pentru compilare 4.43.0
Compilație specifică hash a770d6c609235bbb24fe
Timp de compilare în milisecunde 522
Numărul de module 8
Numărul de bucăți 1
Număr de active 2

Graficul dependenței

Dacă facem clic pe secțiunea dependență, vom obține o diagramă similară și un tabel care prezintă diferite dependențe în aplicația noastră, informații detaliate despre fiecare dependență și modul în care acestea sunt conectate între ele.

Grafic de dependență

Acum, aceste statistici de construcție sunt foarte utile, dar din moment ce ne vom concentra exclusiv pe slăbirea și optimizarea dimensiunii pachetului, vom folosi un instrument specializat Webpack numit webpack-bundle-analyzer. Acest instrument vă va permite să vizualizați dimensiunea fișierelor de ieșire Webpack și să vă afișeze o hartă interactivă cu zoom. Să-l configurăm pentru proiectul nostru. Primul lucru este să instalați pachetul:

Următorul lucru pe care trebuie să-l facem este să setăm configul aferent în fișierul webpack.config.js:

Acum tot ce trebuie să faceți este să conectați un script în package.json pentru a rula analizorul:

Deci, după ce rulăm npm run-script bundle-report, obținem o reprezentare vizuală a ceea ce se află în pachetul nostru și vedem care dintre ele iau cea mai mare parte a dimensiunii. Iată cum arată acest lucru pentru proiectul nostru:

Analizator de pachete Webpack

Așa cum putem vedea, dependențele React ocupă cea mai mare parte a dimensiunii pachetului. Să vedem dacă putem face ceva în acest sens, pentru a ne ajuta să reducem dimensiunea totală a pachetului.

Optimizarea pachetului # 1: Rulați Webpack în modul de producție

Această strategie pentru optimizarea pachetului și reducerea dimensiunii totale a pachetului este ușoară și simplă. Webpack are un steag de producție (-p) care face puține optimizări din cutie. Deci, dacă executăm scriptul nostru de construire cu comanda de mai jos, ar trebui să obținem o optimizare:

După ce rulăm acest lucru, putem vedea că dimensiunea pachetului nostru va scădea de la 970 KB la 128KB. Dar cum a reușit Webpack această optimizare drastică cu o comandă atât de simplă? Ei bine, există în principal două motive pentru aceasta:

  • Sub capotă, React va folosi un plugin numit UglifyJS care gestionează reducerea codului și eliminarea codului mort, eliminând orice spațiu alb inutil sau cod neutilizat.
  • De asemenea, setează NODE_ENV la producție. În acest fel, unele pachete precum React nu vor include cod de depanare

Acesta este un pas bun spre reducerea dimensiunii pachetului și reducerea timpului de încărcare pentru utilizatori. Să vedem ce mai putem face.

Optimizarea pachetului # 2: Instalați biblioteci alternative mai ușoare

Dimensiunea pachetului React este încă cam mare (124 KB în proiectul nostru), chiar și după optimizarea anterioară. Verificând raportul webpack-bundle-analyzer, putem vedea că React a luat o cantitate semnificativă din dimensiunea pachetului nostru. Deci, vom lua în considerare înlocuirea acestuia cu o versiune mai ușoară a React numită preact cu dimensiunea de doar 3 KB.

Când instalăm acest pachet ca dependență, primim atât suportul nucleului API React, cât și suportul DOM; și ca pas suplimentar, putem instala preact-compat ca strat de compatibilitate pentru React cu dimensiunea de 2 KB. În acest fel, putem folosi preactul ca înlocuitor pentru React în proiectul nostru. Preact este mai performant decât React, așa cum putem vedea în comparația de mai jos a performanței între diferite biblioteci care au fost utilizate pentru a construi un simplu benchmark MVC „De făcut”:

Sursa: https://developit.github.io/

Așadar, acum vom instala Preact pentru proiectul nostru și vom vedea cum afectează dimensiunea pachetului nostru. Mai întâi instalăm preact și preact-compat:

Și atunci trebuie doar să setăm alias config în wepack.config.js, pentru a face compatibilitatea acestei biblioteci cu toate codurile React:

Deci, după ce acest lucru este configurat și rulat npm run-script bundle-report, obținem următoarea analiză a pachetului. În această diagramă interactivă, putem vedea că dimensiunile pachetelor legate de React se micșorează acum la aproximativ 23 KB în comparație cu ceea ce era înainte ca 124 KB. Aceasta este o reducere excelentă a dimensiunii pachetului pentru noi:

Utilizarea webpack-bundle-analyzer ne permite să vedem vizual pachetele care sunt instalate în aplicația noastră. Dacă un pachet a ocupat mult spațiu, am putea lua în considerare strategii precum înlocuirea acestuia cu o bibliotecă de versiuni mai ușoare (așa cum am făcut mai sus).

Concluzie

Până în prezent, am reușit să reducem dimensiunea pachetului nostru de la 970 KB la 23 KB, ceea ce reprezintă o scădere de 42 de ori a dimensiunii pachetului nostru. De asemenea, amintiți-vă că structura și dependențele proiectului nostru erau mici, dar luarea unei inițiative în reducerea dimensiunii pachetului pentru proiecte mai mari și mai complicate poate fi mai benefică.

Iată câțiva pași potențiali pe care îi puteți face pentru a reduce dimensiunea pachetului și timpul de încărcare și pentru a crește performanța.

  • Luați în considerare rescrierea bibliotecilor de dimensiuni mari în care este posibil să nu aveți nevoie de toate funcționalitățile sale. De exemplu, mulți dezvoltatori folosesc Moment.js pentru analizarea și validarea datelor în JavaScript, care este de dimensiuni mari, dar nu toată lumea are nevoie de întreaga bibliotecă pentru analize simple de date. Luați în considerare scrierea unor funcții simple de utilitate în loc să vă bazați pe biblioteci mari
  • Verificați dacă utilizați doar un modul de funcții al bibliotecii care poate fi importat singur fără a importa întreaga bibliotecă. Un bun exemplu al acestui caz de utilizare este lodash, pentru care puteți importa oricare dintre funcțiile sale de utilitate bibliotecă separat
  • În cele din urmă, luați în considerare divizarea codului. Nu fiecare dependență trebuie încărcată pe fiecare încărcare a paginii, deci ar avea sens să le grupați separat. De exemplu, dependențele NPM externe nu se schimbă la fel de mult ca și codul aplicației noastre. Deci, împărțirea acestora într-un pachet separat ar permite browserului să le cache în timp ce acestea nu au fost modificate și, prin urmare, ar reduce numărul de pachete care trebuie încărcate la fiecare încărcare a paginii

Resurse

  • https://www.sciencefocus.com/future-technology/can-computers-keep-getting-faster/
  • https://www.keycdn.com/support/the-growth-of-web-page-size
  • https://medium.com/better-programming/reducing-js-bundle-size-58dc39c10f9c
  • https://www.contentful.com/blog/2017/10/10/put-your-webpack-on-a-diet-part-1/
  • https://medium.com/@rajaraodv/using-preact-instead-of-react-70f40f53107c
  • https://medium.com/a-young-devoloper/analyzing-and-reducing-react-bundle-size-bb2d2577b22a
  • https://codeengineered.com/blog/why-front-end-performance-important/
  • http://www.stevesouders.com/blog/2012/02/10/the-performance-golden-rule/
  • https://www.keycdn.com/support/the-growth-of-web-page-size
  • https://medium.com/better-programming/reducing-js-bundle-size-58dc39c10f9c
  • https://medium.com/@gimenete/how-javascript-bundlers-work-1fc0d0caf2da
  • https://blog.jakoblind.no/3-ways-to-reduce-webpack-bundle-size/

Vizibilitate deplină în aplicațiile React de producție

LogRocket este ca un DVR pentru aplicații web, înregistrând literalmente tot ce se întâmplă în aplicația dvs. React. În loc să ghiciți de ce apar problemele, puteți agrega și raporta în ce stare se afla aplicația dvs. când a apărut o problemă. LogRocket monitorizează, de asemenea, performanța aplicației dvs., raportând cu valori cum ar fi încărcarea procesorului clientului, utilizarea memoriei clientului și multe altele.

Pachetul middleware LogRocket Redux adaugă un strat suplimentar de vizibilitate în sesiunile dvs. de utilizator. LogRocket înregistrează toate acțiunile și starea din magazinele dvs. Redux.

Modernizează modul de depanare a aplicațiilor React - începe monitorizarea gratuit.