Cum să optimizați aplicația web PHP Laravel pentru performanțe ridicate?

Laravel este multe lucruri. Dar repede nu este unul dintre ei. Să învățăm câteva trucuri ale comerțului pentru a face să meargă mai repede!


Niciun dezvoltator PHP nu este atins Laravel aceste zile. Ei sunt fie un dezvoltator de nivel mediu sau de nivel mediu, care adoră dezvoltarea rapidă pe care o oferă Laravel, fie sunt un dezvoltator senior care este obligat să învețe Laravel din cauza presiunilor pieței.

Oricum, nu neagă că Laravel a revitalizat ecosistemul PHP (cu siguranță, aș fi părăsit lumea PHP cu mult timp în urmă, dacă Laravel nu ar fi fost acolo).

Un fragment de laudă de sine (oarecum justificată) de la Laravel

Cu toate acestea, având în vedere că Laravel se apleacă înapoi pentru a vă face lucrurile mai ușoare, înseamnă că dedesubt, face eforturi și tone de muncă pentru a vă asigura că aveți o viață confortabilă ca dezvoltator. Toate caracteristicile „magice” ale lui Laravel care par să funcționeze au straturi pe straturi de cod care trebuie bifate de fiecare dată când se execută o caracteristică. Chiar și o simplă Excepție urmărește cât de adâncă este gaura iepurelui (observați unde începe eroarea, până la nucleul principal):

Pentru ceea ce pare a fi o eroare de compilare într-una dintre vizualizări, există 18 apeluri funcționale de urmărit. Personal am întâlnit 40 de persoane și ar putea fi mai ușor dacă utilizați alte biblioteci și pluginuri.

În mod implicit, acest strat pe straturile de cod, face ca Laravel să fie lent.

Cât de lent este Laravel?

Sincer, este imposibil să răspunzi la această întrebare din mai multe motive.

Primul, nu există un standard acceptat, obiectiv, sensibil pentru măsurarea vitezei aplicațiilor Web. Mai repede sau mai lent comparativ cu ce? În ce condiții?

Al doilea, o aplicație Web depinde de atâtea lucruri (bază de date, sistem de fișiere, rețea, cache etc.) încât este simplu de prost să vorbim despre viteză. O aplicație Web foarte rapidă cu o bază de date foarte lentă este o aplicație web foarte lentă. ��

Dar această incertitudine este tocmai de ce reperele sunt populare. Chiar dacă nu înseamnă nimic (vezi acest și acest), ele oferă un cadru de referință și ne ajută să ne înnebunim. Prin urmare, cu mai mulți vârfuri de sare gata, să facem o idee greșită și aspră de viteză în cadrul cadrelor PHP.

Urmând acest GitHub destul de respectabil sursă, iată cum se aliniază cadrele PHP în comparație:

Este posibil să nu observați nici Laravel aici (chiar dacă aruncați cu adevărat tare) decât dacă vă aruncați cazul până la capătul cozii. Da, dragi prieteni, Laravel vine ultima! Acum, acordate, majoritatea acestor „cadre” nu sunt foarte practice sau chiar utile, dar ne spune cât de lenev este Laravel în comparație cu alte mai populare..

În mod normal, această „lentilitate” nu este prezentată în aplicații, deoarece aplicațiile noastre web de zi cu zi ating foarte rar un număr mare. Dar, odată ce se descurcă (să zicem, în concordanță de 200-500 în sus), serverele încep să sufle și să moară. Este momentul în care chiar aruncarea mai multor hardware la problema nu o reduce și facturile de infrastructură urcă atât de repede încât idealurile tale înalte de cloud computing se prăbușesc..

Dar hei, înveselește-te! Acest articol nu este despre ceea ce nu se poate face, ci despre ceea ce se poate face. ��

O veste bună este că poți face multe pentru ca aplicația Laravel să meargă mai repede. De câteva ori rapid. Da, nu glumește. Puteți face ca aceeași bază de cod să devină balistică și să economisiți câteva sute de dolari pe facturile de infrastructură / gazduire în fiecare lună. Cum? Să ajungem la asta.

Patru tipuri de optimizări

În opinia mea, optimizarea se poate face pe patru niveluri distincte (atunci când vine vorba de aplicații PHP, adică):

  1. Limba de nivel: Acest lucru înseamnă că utilizați o versiune mai rapidă a limbii și evitați anumite caracteristici / stiluri de codare în limba care vă încetinește codul.
  2. Cadrul de nivel: Acestea sunt lucrurile pe care le vom aborda în acest articol.
  3. Infrastructura de nivel: Reglarea managerului de proces PHP, server web, bază de date etc.
  4. Hardware-nivel: Trecerea la un furnizor de hosting hardware mai bun, mai rapid și mai puternic.

Toate aceste tipuri de optimizări își au locul (de exemplu, optimizarea php-fpm este destul de critică și puternică). Dar obiectivul acestui articol va fi optimizările pur de tip 2: cele legate de cadru.

Apropo, nu există nicio justificare în spatele numerotării și nu este un standard acceptat. Tocmai am făcut aceste lucruri. Vă rugăm să nu mă citați vreodată și să spuneți: „Avem nevoie de optimizarea tipului 3 pe serverul nostru” sau conducerea echipei dvs. vă va ucide, mă va găsi și apoi mă va ucide și pe mine. ��

Și acum, în sfârșit, ajungem pe pământul promis.

Fiți la curent cu interogările bazei de date n + 1

Problema de interogare n + 1 este una comună atunci când sunt utilizate ORM-uri. Laravel are ORM-ul său puternic numit Eloquent, care este atât de frumos, atât de convenabil, încât de multe ori uităm să privim ce se întâmplă.

Luați în considerare un scenariu foarte comun: afișarea listei tuturor comenzilor plasate de o listă dată de clienți. Acest lucru este destul de comun în sistemele de comerț electronic și în orice interfețe de raportare, în general, unde trebuie să afișăm toate entitățile legate de unele entități.

În Laravel, am putea imagina o funcție de controler care face treaba astfel:

clasa OrdersController extinde Controller
{
// …

funcția publică getAllByCustomers (Cerere $ cerere, matricea $ id) {
Clienti $ = Client :: findMany ($ id);
$ comenzi = colecta (); // colecție nouă

foreach (clienți $ ca $ client) {
$ comenzi = $ comenzi->îmbinare ($ pentru clienți->Comenzi);
}

vizualizare returnare (‘admin.reports.orders’, [‘comenzi’ => ordinele $]);
}
}

Dulce! Și mai important, elegant, frumos. ����

Din păcate, este o modalitate dezastruoasă de a scrie cod în Laravel.

Iata de ce.

Când solicităm ORM să caute clienții dat, se generează o interogare SQL ca aceasta:

SELECTA * DE la clienții WHERE ID IN (22, 45, 34,.);

Ceea ce este exact așa cum era de așteptat. Ca urmare, toate rândurile returnate sunt stocate în colecția $ clienți în funcția de controler.

Acum facem buclă peste fiecare client unul câte unul și obținem comenzile lor. Aceasta execută următoarea interogare . . .

SELECT * DIN comenzi WHERE client_id = 22;

. . . de câte ori există clienți.

Cu alte cuvinte, dacă trebuie să obținem datele comenzii pentru 1000 de clienți, numărul total de interogări ale bazei de date executate va fi de 1 (pentru preluarea tuturor datelor clienților) + 1000 (pentru preluarea datelor comenzii pentru fiecare client) = 1001. Aceasta este de unde provine numele n + 1.

Putem face mai bine? Cu siguranță! Folosind ceea ce se cunoaște încărcarea dornică, putem forța ORM să efectueze o ÎNREGISTRARE și să returneze toate datele necesare într-o singură interogare! Asa:

$ comenzi = Client :: findMany ($ id)->cu ( „ordine“)->obține();

Structura de date rezultată este sigur, dar sigur, dar datele de comandă pot fi ușor extrase. Interogarea unică rezultată, în acest caz, este ceva de genul:

SELECT * DE la clienți INNER JOIN comenzi ON clients.id = comenzi.customer_id WHERE clients.id IN (22, 45,..);

O singură interogare este, desigur, mai bună decât o mie de interogări suplimentare. Imaginează-ți ce s-ar întâmpla dacă ar exista 10.000 de clienți care să proceseze! Sau Doamne ferește dacă am fi dorit să afișăm și articolele conținute în fiecare ordine! Amintiți-vă, numele tehnicii este încărcat cu nerăbdare și este aproape întotdeauna o idee bună.

Cache configurația!

Unul dintre motivele pentru flexibilitatea Laravel este tonul de fișiere de configurare care fac parte din cadru. Doriți să schimbați cum / unde sunt stocate imaginile?

Ei bine, trebuie doar să schimbați fișierul config / filesystems.php (cel puțin la scriere). Vrei să lucrezi cu mai mulți drivere de coadă? Nu ezitați să le descrieți în config / queue.php. Tocmai am numărat și am constatat că există 13 fișiere de configurare pentru diferite aspecte ale cadrului, asigurându-vă că nu veți fi dezamăgit indiferent de ceea ce doriți să schimbați.

Având în vedere natura PHP, de fiecare dată când apare o nouă solicitare Web, Laravel se trezește, pornește totul și analizează toate aceste fișiere de configurare pentru a descoperi cum să faci lucrurile diferit de data aceasta. Doar că este o prostie dacă nu s-a schimbat nimic în ultimele zile! Reconstruirea config-ului la fiecare solicitare este o deșeu care poate fi (de fapt, trebuie evitată), iar ieșirea este o comandă simplă pe care Laravel o oferă:

php artisan config: cache

Ceea ce face este să combinați toate fișierele de configurare disponibile într-unul singur și cache-ul este undeva pentru regăsire rapidă. Data viitoare când va exista o solicitare Web, Laravel va citi pur și simplu acest singur fișier și va începe.

Acestea fiind spuse, cache-ul de configurare este o operație extrem de delicată care vă poate exploda în față. Cea mai mare notă este că, după ce ați emis această comandă, funcția env () apelează de oriunde, cu excepția fișierelor de configurare vor reveni nul!

Are sens atunci când te gândești la asta. Dacă utilizați memoria de cache a configurației, spuneți cadrul: „Știți ce, cred că am configurat lucrurile frumos și sunt 100% sigur că nu vreau să se schimbe”. Cu alte cuvinte, așteptați ca mediul să rămână static, pentru care sunt fișierele .env.

Cu acest lucru, iată câteva reguli de cache a configurației, acoperite de fier, sacre și de neînfrânat:

  1. Faceți-o doar pe un sistem de producție.
  2. Faceți-o doar dacă sunteți cu adevărat, sigur că doriți să înghețați configurația.
  3. În cazul în care ceva nu merge bine, anulați setarea cu cache artizanal php: clar
  4. Rugați-vă ca pagubele aduse afacerii să nu fie importante!

Reduceți serviciile automate

Pentru a fi de ajutor, Laravel încarcă o mulțime de servicii atunci când se trezește. Acestea sunt disponibile în fișierul config / app.php ca parte a cheii „furnizorilor”. Să aruncăm o privire la ce am în cazul meu:

/ *
|————————————————————————–
| Furnizori de servicii automate
|————————————————————————–
|
| Furnizorii de servicii enumerați aici vor fi încărcați automat pe
| cerere către cererea dvs. Nu ezitați să vă adăugați propriile servicii
| acest tablou pentru a acorda funcționalități extinse aplicațiilor dvs..
|
* /

“furnizori” => [

/ *
* Furnizorii de servicii Laravel Framework…
* /
Illuminate \ Auth \ AuthServiceProvider :: clasa,
Illuminate \ Difuzare \ BroadcastServiceProvider :: clasa,
Illuminate \ autobuz \ BusServiceProvider :: clasa,
Illuminate \ cache \ CacheServiceProvider :: clasa,
Illuminate \ Fundația \ Furnizori \ ConsoleSupportServiceProvider :: clasa,
Illuminate \ Cookie \ CookieServiceProvider :: clasa,
Illuminate \ Baza de date \ DatabaseServiceProvider :: clasa,
Illuminate \ Criptare \ EncryptionServiceProvider :: clasa,
Illuminate \ Filesystem \ FilesystemServiceProvider :: clasa,
Illuminate \ Fundația \ Furnizori \ FoundationServiceProvider :: clasa,
Illuminate \ hashing \ HashServiceProvider :: clasa,
Illuminate \ Mail \ MailServiceProvider :: clasa,
Illuminate \ Notificări \ NotificationServiceProvider :: clasa,
Illuminate \ paginare \ PaginationServiceProvider :: clasa,
Illuminate \ Pipeline \ PipelineServiceProvider :: clasa,
Illuminate \ Coadă \ QueueServiceProvider :: clasa,
Illuminate \ Redis \ RedisServiceProvider :: clasa,
Illuminate \ Auth \ Parolele \ PasswordResetServiceProvider :: clasa,
Illuminate \ Session \ SessionServiceProvider :: clasa,
Illuminate \ Traducere \ TranslationServiceProvider :: clasa,
Illuminate \ Validare \ ValidationServiceProvider :: clasa,
Illuminate \ View \ ViewServiceProvider :: clasa,

/ *
* Furnizori de servicii de pachete…
* /

/ *
* Furnizori de servicii de aplicații…
* /
App \ Furnizori \ AppServiceProvider :: clasa,
App \ Furnizori \ AuthServiceProvider :: clasa,
// App \ Furnizori \ BroadcastServiceProvider :: clasa,
App \ Furnizori \ EventServiceProvider :: clasa,
App \ Furnizori \ RouteServiceProvider :: clasa,

],

Încă o dată, am numărat și sunt 27 de servicii listate! Acum, este posibil să aveți nevoie de toate, dar este puțin probabil.

De exemplu, se întâmplă să construiesc o API REST în acest moment, ceea ce înseamnă că nu am nevoie de Furnizorul de servicii de sesiune, de furnizor de servicii etc. Și din moment ce fac câteva lucruri în felul meu și nu urmează setările prestabilite de cadru. , De asemenea, pot dezactiva Furnizorul de servicii Auth, Furnizorul de servicii de paginare, Furnizorul de servicii de traducere și așa mai departe. În total, aproape jumătate dintre acestea sunt inutile pentru cazul meu de utilizare.

Aruncați o privire lungă și dură la aplicația dvs. Are nevoie de toți acești furnizori de servicii? Dar pentru numele lui Dumnezeu, vă rog să nu comentați orbește aceste servicii și să faceți eforturi către producție! Efectuați toate testele, verificați manual lucrurile pe mașini dev și de stadializare și fiți foarte paranoici înainte de a trage declanșatorul. ��

Fiți înțelepți cu teancuri de middleware

Când aveți nevoie de o procesare personalizată a cererii Web primite, crearea unui nou middleware este răspunsul. Acum, este tentant să deschizi aplicația / Http / Kernel.php și să lipiți middleware-ul în web sau api stack; în acest fel, acesta devine disponibil în aplicație și dacă nu face ceva intruziv (cum ar fi logarea sau notificarea, de exemplu).

Cu toate acestea, pe măsură ce aplicația crește, această colecție de middleware globală poate deveni o povară silențioasă pentru aplicație dacă toate (sau majoritatea) sunt prezente la fiecare solicitare, chiar dacă nu există niciun motiv de afaceri pentru asta.

Cu alte cuvinte, aveți grijă unde adăugați / aplicați un nou middleware. Poate fi mai convenabil să adăugați ceva la nivel global, dar penalitatea de performanță este foarte mare pe termen lung. Știu că durerea va trebui să suferi dacă ar trebui să aplici selectiv middleware de fiecare dată când are loc o nouă schimbare, dar este o durere pe care am să o doresc și să o recomand de bună voie!

Evitați ORM (uneori)

În timp ce Eloquent face ca multe aspecte ale interacțiunii DB să fie plăcute, aceasta costă viteza. Fiind un mapper, ORM nu numai că trebuie să preia înregistrări din baza de date, ci și să instantaneze obiectele model și să le hidrateze (completează) cu date de coloană.

Deci, dacă faceți un simplu utilizator $ = User :: all () și există, să zicem, 10.000 de utilizatori, cadrul va prelua 10.000 de rânduri din baza de date și va face intern 10.000 de utilizatori noi () și va completa proprietățile lor cu datele relevante . Aceasta este o cantitate masivă de lucrări efectuate în culise, iar dacă baza de date este locul în care aplicația devine un blocaj, ocolirea ORM este o idee bună uneori..

Acest lucru este valabil mai ales în cazul interogărilor SQL complexe, unde ar trebui să sari o mulțime de cercuri și să scrii închideri în timpul închiderilor și să termini totuși cu o interogare eficientă. În astfel de cazuri, este preferată efectuarea unui DB :: raw () și scrierea interogării manual.

Merge de acest studiul performanței, chiar și pentru inserții simple, Eloquent este mult mai lent pe măsură ce numărul înregistrărilor crește:

Folosiți memoria cache cât mai mult posibil

Unul dintre cele mai bine păstrate secrete ale optimizării aplicațiilor Web este memoria cache.

Pentru cei neinițiați, memorarea în cache înseamnă precomputarea și stocarea rezultatelor scumpe (scumpe în ceea ce privește utilizarea procesorului și a memoriei) și pur și simplu returnarea acestora atunci când se repetă aceeași interogare.

De exemplu, într-un magazin de comerț electronic, s-ar putea întâlni cel al celor 2 milioane de produse, de cele mai multe ori oamenii sunt interesați de cele care sunt proaspăt stocate, într-un anumit interval de preț și pentru o anumită categorie de vârstă. Interogarea bazei de date pentru aceste informații este risipitoare – din moment ce interogarea nu se schimbă adesea, este mai bine să stochezi aceste rezultate undeva pe care le putem accesa rapid.

Laravel are suport integrat pentru mai multe tipuri de cache. Pe lângă utilizarea unui driver de cache și construirea sistemului de cache de la sol, este posibil să doriți să utilizați câteva pachete Laravel care vă facilitează model de cache, interogare în cache, etc.

Dar rețineți că, dincolo de un anumit caz de utilizare simplificată, pachetele pre-construite din memoria cache pot provoca mai multe probleme decât rezolvă.

Preferă memorarea în cache în memorie

Când cachezi ceva în Laravel, ai mai multe opțiuni de unde să stochezi calculul rezultat care trebuie să fie memorat în cache. Aceste opțiuni sunt cunoscute și sub denumirea de drivere de cache. Așadar, deși este posibil și perfect rezonabil să folosiți sistemul de fișiere pentru stocarea rezultatelor din memoria cache, nu este în realitate ceea ce trebuie să fie memoria cache.

În mod ideal, doriți să utilizați un cache în memorie (care trăiește în RAM în totalitate) ca Redis, Memcached, MongoDB, etc., astfel încât, în cazul încărcărilor mai mari, memoria cache servește o utilizare vitală, mai degrabă decât să devină un blocaj în sine.

Acum, s-ar putea să credeți că un disc SSD este aproape același cu utilizarea unui stick RAM, dar nici nu este aproape. Chiar și informal valori de referință arată că RAM depășește SSD de 10-20 de ori atunci când vine vorba de viteză.

Sistemul meu preferat când vine vorba de cache este Redis. Este ridicol de rapid (100.000 de operații citite pe secundă sunt obișnuite), iar pentru sistemele de cache foarte mari, pot fi evoluate într-un grup uşor.

Cache rutele

La fel ca configurația aplicației, rutele nu se schimbă prea mult în timp și sunt un candidat ideal pentru memorie în cache. Acest lucru este valabil mai ales dacă nu puteți suporta fișiere mari ca mine și ajungeți să împărțiți web.php și api.php în mai multe fișiere. O singură comandă Laravel ambalează toate rutele disponibile și le păstrează la îndemână pentru accesul viitor:

rută artizanală php: cache

Și când terminați adăugând sau schimbând rutele, pur și simplu faceți:

traseu artizanal php: clar

Optimizarea imaginii și CDN

Imaginile sunt inima și sufletul majorității aplicațiilor Web. Întâmplător, sunt și cei mai mari consumatori de lățime de bandă și unul dintre cele mai mari motive pentru aplicații / site-uri web lente. Dacă pur și simplu stocați imaginile încărcate în mod naiv pe server și le trimiteți înapoi în răspunsurile HTTP, veți lăsa o oprire masivă a posibilităților de optimizare.

Prima mea recomandare este să nu stocați imagini la nivel local – există problema pierderii de date pentru a face față și, în funcție de regiunea geografică în care se află clientul dvs., transferul de date poate fi dureros de lent.

În schimb, mergeți pentru o soluție de genul Cloudinary care redimensionează și optimizează automat imaginile din zbor.

Dacă acest lucru nu este posibil, utilizați ceva precum Cloudflare pentru a memora în cache și a servi imagini în timp ce sunt stocate pe serverul dvs..

Și chiar dacă acest lucru nu este posibil, modificarea puțin a software-ului serverului web pentru a comprima activele și a direcționa browserul vizitatorului către lucrurile din cache, face o diferență. Iată cum ar arăta un fragment de configurare Nginx:

Server {

# fișier trunchiat

# setări de compresie gzip
gzip pornit;
gzip_comp_level 5;
gzip_min_length 256;
gzip_proxied oricare;
gzip_vary pornit;

# control cache browser
locație ~ * \. (ico | css | js | gif | jpeg | jpg | png | woff | ttf | otf | svg | woff2 | eot) $ {
expiră 1d;
access_log off;
add_header Pragma publică;
add_header Cache-Control "public, vârsta maximă = 86400";
}
}

Sunt conștient că optimizarea imaginii nu are nicio legătură cu Laravel, dar este un truc atât de simplu și puternic (și este adesea neglijat), care nu m-ar putea ajuta.

Optimizarea autoloader

Auto-încărcarea este o caracteristică îngrijită, care nu este atât de veche în PHP, care a salvat în mod cert limba de la doom. Acestea fiind spuse, procesul de găsire și încărcare a clasei relevante prin descifrarea unui anumit șir de spații de nume necesită timp și poate fi evitat în implementările de producție, unde este de dorit performanțe ridicate. Încă o dată, Laravel are o soluție de comandă unică pentru aceasta:

instalare compozitor –optimize-autoloader –no-dev

Faceți prieteni cu cozi

cozile sunt modul în care prelucrați lucrurile atunci când există multe dintre ele și fiecare dintre ele are nevoie de câteva milisecunde pentru a fi completate. Un exemplu bun este trimiterea de e-mailuri – un caz de utilizare pe scară largă în aplicațiile web este de a fotografia câteva e-mailuri de notificare atunci când un utilizator efectuează unele acțiuni.

De exemplu, într-un produs recent lansat, s-ar putea să doriți ca conducerea companiei (aproximativ 6-7 adrese de e-mail) să fie notificată ori de câte ori cineva plasează o comandă peste o anumită valoare. Presupunând că gateway-ul dvs. de e-mail poate răspunde la solicitarea dvs. SMTP în 500ms, vorbim despre o așteptare bună de 3-4 secunde pentru utilizator înainte de confirmarea comenzii. de acord.

Remediul este să stochezi lucrările pe măsură ce intră, să le spui utilizatorului că totul a decurs bine și să le proceseze (câteva secunde) mai târziu. Dacă există o eroare, lucrările în coadă pot fi reluate de câteva ori înainte de a se declara că au eșuat.

Credite: Microsoft.com

În timp ce un sistem de coadă complică puțin configurarea (și adaugă unele monitorizări), este indispensabil într-o aplicație Web modernă.

Optimizarea activelor (Laravel Mix)

Pentru orice active frontale din aplicația Laravel, asigurați-vă că există o conductă care compilează și minimizează toate fișierele de activ. Cei care sunt confortabili cu un sistem de pachet, cum ar fi Webpack, Gulp, colet etc., nu trebuie să deranjeze, dar dacă nu faceți acest lucru deja, Laravel Mix este o recomandare solidă.

Mix este un înveliș ușor (și încântător, cu toată cinstea!) În jurul Webpack, care are grijă de toate fișierele CSS, SASS, JS etc. Un fișier .mix.js tipic poate fi la fel de mic ca acesta și încă mai poate face minuni:

const mix = necesită (‘laravel-mix’);

mix.js (‘resurse / js / app.js’, ‘public / js’)
.sass (‘resurse / sass / app.scss’, ‘public / css’);

Acest lucru are în mod automat grijă de importuri, minificare, optimizare și întregul shebang atunci când sunteți gata pentru producție și rulați producția de rulare npm. Mix are grijă nu doar de fișierele JS și CSS tradiționale, ci și de componentele Vue și React pe care le-ați putea avea în fluxul de lucru al aplicației..

Mai multe informatii aici!

Concluzie

Optimizarea performanței este mai multă artă decât știință – știind cum și cât de mult este important decât ceea ce trebuie făcut. Acestea fiind spuse, nu există niciun sfârșit pentru cât și pentru tot ce poți optimiza într-o aplicație Laravel.

Dar orice ai face, aș dori să te las cu câteva sfaturi de despărțire – optimizarea ar trebui făcută atunci când există un motiv solid și nu pentru că sună bine sau pentru că sunteți paranoic în legătură cu performanța aplicației pentru 100.000+ utilizatori, în realitate sunt doar 10.

Dacă nu sunteți sigur dacă doriți sau nu să optimizați aplicația, nu trebuie să dați cuibul proverbiale. O aplicație care funcționează care se simte plictisitoare, dar face exact ceea ce trebuie, este de zece ori mai de dorit decât o aplicație care a fost optimizată într-o supermașină hibridă mutantă, dar care se încadrează din când în când.

Și, pentru ca newbiew să devină un maestru Laravel, verificați acest lucru curs online.

Fie ca aplicațiile dvs. să ruleze mult, mult mai repede! ��

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map