Evitarea capcanelor codului integrat automat

Publicat: 2022-03-10
Rezumat rapid ↬ Folosirea excesivă a codului CSS sau JS inline, spre deosebire de difuzarea codului prin resurse statice, poate dăuna performanței site-ului. În acest articol, vom învăța cum să încărcăm cod dinamic prin fișiere statice, evitând dezavantajele prea multor cod inline.

Inlinierea este procesul de includere a conținutului fișierelor direct în documentul HTML: fișierele CSS pot fi aliniate în interiorul unui element de style , iar fișierele JavaScript pot fi aliniate într-un element de script :

 <style> /* CSS contents here */ </style> <script> /* JS contents here */ </script>

Imprimând codul deja în ieșirea HTML, inlining evită solicitările de blocare a randării și execută codul înainte ca pagina să fie randată. Ca atare, este util pentru îmbunătățirea performanței percepute a site-ului (adică timpul necesar pentru ca o pagină să devină utilizabilă). De exemplu, putem folosi tamponul de date livrat imediat la încărcarea site-ului (aproximativ 14 kb) pentru a inline stilurile esențiale, inclusiv stilurile de conținut de deasupra paginii (așa cum se făcuse pe site-ul anterior Smashing Magazine) și dimensiunile fonturilor și lățimile și înălțimile aspectului pentru a evita o re-rendare agitată a aspectului când restul datelor sunt livrate .

Cu toate acestea, atunci când este exagerat, codul de inline poate avea, de asemenea, efecte negative asupra performanței site-ului: deoarece codul nu poate fi stocat în cache, același conținut este trimis clientului în mod repetat și nu poate fi pre-memorizat prin Service Workers sau stocate în cache și accesate dintr-o rețea de livrare de conținut. În plus, scripturile inline sunt considerate nesigure atunci când implementează o Politică de securitate a conținutului (CSP). Apoi, este o strategie sensibilă de a integra acele părți critice de CSS și JS care fac site-ul să se încarce mai rapid, dar evitate pe cât posibil altfel.

Cu scopul de a evita integrarea, în acest articol vom explora cum să convertim codul inline în elemente statice: în loc să tipărim codul în ieșirea HTML, îl salvăm pe disc (creând efectiv un fișier static) și adăugăm <script> corespunzător. <script> sau <link> pentru a încărca fișierul.

Să începem!

Lectură recomandată : Securitatea WordPress ca proces

Mai multe după săritură! Continuați să citiți mai jos ↓

Când să evitați încadrarea

Nu există o rețetă magică care să stabilească dacă un cod trebuie să fie integrat sau nu, cu toate acestea, poate fi destul de evident când un cod nu trebuie să fie înliniat: atunci când implică o bucată mare de cod și când nu este necesar imediat.

De exemplu, site-urile WordPress includ șabloanele JavaScript pentru a reda Media Manager (accesibil în pagina Media Library sub /wp-admin/upload.php ), imprimând o cantitate considerabilă de cod:

O captură de ecran a codului sursă pentru pagina Media Library
Șabloane JavaScript integrate de WordPress Media Manager.

Ocupând o totalitate de 43 kb, dimensiunea acestei bucăți de cod nu este de neglijat și, deoarece se află în partea de jos a paginii, nu este necesară imediat. Prin urmare, ar fi foarte logic să difuzați acest cod prin intermediul activelor statice sau să-l imprimați în ieșirea HTML.

Să vedem în continuare cum să transformăm codul inline în active statice.

Declanșarea creării fișierelor statice

Dacă conținutul (cele care urmează să fie inlineate) provin dintr-un fișier static, atunci nu este mare lucru de făcut decât să solicitați pur și simplu acel fișier static în loc să introduceți codul.

Pentru codul dinamic, totuși, trebuie să planificăm cum/când să generăm fișierul static cu conținutul său. De exemplu, dacă site-ul oferă opțiuni de configurare (cum ar fi schimbarea schemei de culori sau a imaginii de fundal), când ar trebui generat fișierul care conține noile valori? Avem următoarele oportunități pentru a crea fișiere statice din codul dinamic:

  1. La cerere
    Când un utilizator accesează conținutul pentru prima dată.
  2. Cu privire la schimbările
    Când sursa pentru codul dinamic (de exemplu, o valoare de configurare) s-a schimbat.

Să luăm în considerare mai întâi la cerere. Prima dată când un utilizator accesează site-ul, să zicem prin /index.html , fișierul static (ex header-colors.css ) nu există încă, așa că trebuie generat atunci. Succesiunea evenimentelor este următoarea:

  1. Utilizatorul solicită /index.html ;
  2. La procesarea cererii, serverul verifică dacă fișierul header-colors.css există. Din moment ce nu, obține codul sursă și generează fișierul pe disc;
  3. Acesta returnează un răspuns clientului, inclusiv eticheta <link rel="stylesheet" type="text/css" href="/staticfiles/header-colors.css">
  4. Browserul preia toate resursele incluse în pagină, inclusiv header-colors.css ;
  5. Până atunci, acest fișier există, deci este servit.

Cu toate acestea, succesiunea evenimentelor ar putea fi, de asemenea, diferită, ceea ce duce la un rezultat nesatisfăcător. De exemplu:

  1. Utilizatorul solicită /index.html ;
  2. Acest fișier este deja stocat în cache de browser (sau de un alt proxy, sau prin Service Workers), astfel încât solicitarea nu este niciodată trimisă la server;
  3. Browserul preia toate resursele incluse în pagină, inclusiv header-colors.css . Această imagine nu este însă stocată în cache în browser, deci cererea este trimisă la server;
  4. Serverul nu a generat încă header-colors.css (de exemplu, tocmai a fost repornit);
  5. Va returna un 404.

Alternativ, am putea genera header-colors.css nu atunci când solicităm /index.html , ci când solicităm /header-colors.css în sine. Cu toate acestea, deoarece acest fișier nu există inițial, cererea este deja tratată ca un 404. Chiar dacă am putea să ne ocolim, modificând antetele pentru a schimba codul de stare la 200 și returnând conținutul imaginii, acesta este un mod groaznic de a face lucrurile, așa că nu vom accepta această posibilitate (suntem mult mai buni decât asta!)

Asta lasă o singură opțiune: generarea fișierului static după ce sursa sa s-a schimbat.

Crearea fișierului static când sursa se schimbă

Vă rugăm să rețineți că putem crea cod dinamic atât din surse dependente de utilizator, cât și din surse dependente de site. De exemplu, dacă tema permite modificarea imaginii de fundal a site-ului și acea opțiune este configurată de administratorul site-ului, atunci fișierul static poate fi generat ca parte a procesului de implementare. Pe de altă parte, dacă site-ul permite utilizatorilor săi să schimbe imaginea de fundal pentru profilurile lor, atunci fișierul static trebuie să fie generat în timpul rulării.

Pe scurt, avem aceste două cazuri:

  1. Configurare utilizator
    Procesul trebuie declanșat atunci când utilizatorul actualizează o configurație.
  2. Configurarea site-ului
    Procesul trebuie declanșat atunci când administratorul actualizează o configurație pentru site sau înainte de implementarea site-ului.

Dacă am lua în considerare cele două cazuri în mod independent, pentru numărul 2 am putea proiecta procesul pe orice stivă de tehnologie dorim. Cu toate acestea, nu dorim să implementăm două soluții diferite, ci o soluție unică care poate aborda ambele cazuri. Și pentru că de la #1 procesul de generare a fișierului static trebuie să fie declanșat pe site-ul care rulează, atunci este convingător să proiectăm acest proces în jurul aceleiași stive de tehnologie pe care rulează site-ul.

La proiectarea procesului, codul nostru va trebui să se ocupe de circumstanțele specifice atât pentru #1, cât și pentru #2:

  • Versiune
    Fișierul static trebuie accesat cu un parametru „versiune”, pentru a invalida fișierul anterior la crearea unui nou fișier static. În timp ce #2 ar putea avea pur și simplu aceeași versiune ca și site-ul, #1 trebuie să folosească o versiune dinamică pentru fiecare utilizator, eventual salvată în baza de date.
  • Locația fișierului generat
    #2 generează un fișier static unic pentru întregul site (de exemplu /staticfiles/header-colors.css ), în timp ce #1 creează un fișier static pentru fiecare utilizator (de ex. /staticfiles/users/leo/header-colors.css ).
  • Evenimentul declanșator
    În timp ce pentru #1 fișierul static trebuie să fie executat în timpul de execuție, pentru #2 poate fi, de asemenea, executat ca parte a unui proces de construire în mediul nostru de staging.
  • Implementare și distribuție
    Fișierele statice din numărul 2 pot fi integrate perfect în pachetul de implementare al site-ului, fără provocări; Cu toate acestea, fișierele statice din numărul 1 nu pot, așa că procesul trebuie să se ocupe de preocupări suplimentare, cum ar fi mai multe servere în spatele unui echilibrator de încărcare (fișierele statice vor fi create doar pe un singur server sau în toate și cum?).

Să proiectăm și să implementăm procesul în continuare. Pentru fiecare fișier static care urmează să fie generat trebuie să creăm un obiect care să conțină metadatele fișierului, să calculăm conținutul acestuia din sursele dinamice și, în final, să salvăm fișierul static pe disc. Ca un caz de utilizare pentru a ghida explicațiile de mai jos, vom genera următoarele fișiere statice:

  1. header-colors.css , cu ceva stil din valorile salvate în baza de date
  2. welcomeuser-data.js , care conține un obiect JSON cu date utilizator sub o variabilă: window.welcomeUserData = {name: "Leo"}; .

Mai jos, voi descrie procesul de generare a fișierelor statice pentru WordPress, pentru care trebuie să ne bazăm stiva pe funcțiile PHP și WordPress. Funcția de generare a fișierelor statice înainte de implementare poate fi declanșată prin încărcarea unei pagini speciale care execută codul scurt [create_static_files] așa cum am descris într-un articol anterior.

Lectură recomandată suplimentară : Making A Service Worker: A Case Study

Reprezentarea fișierului ca obiect

Trebuie să modelăm un fișier ca obiect PHP cu toate proprietățile corespunzătoare, astfel încât să putem atât salva fișierul pe disc într-o locație specifică (de exemplu, fie sub /staticfiles/ sau /staticfiles/users/leo/ ), și să știm cum să solicităm dosar in consecinta. Pentru aceasta, creăm o interfață Resource care returnează atât metadatele fișierului (nume fișier, dir, tip: „css” sau „js”, versiunea și dependențele de alte resurse), cât și conținutul acestuia.

 interface Resource { function get_filename(); function get_dir(); function get_type(); function get_version(); function get_dependencies(); function get_content(); }

Pentru ca codul să fie întreținut și reutilizabil, urmăm principiile SOLID, pentru care setăm o schemă de moștenire a obiectelor pentru resurse pentru a adăuga treptat proprietăți, pornind de la clasa abstractă ResourceBase de la care toate implementările noastre de Resource vor moșteni:

 abstract class ResourceBase implements Resource { function get_dependencies() { // By default, a file has no dependencies return array(); } }

După SOLID, creăm subclase ori de câte ori proprietățile diferă. După cum sa menționat mai devreme, locația fișierului static generat și versiunea pentru a-l solicita vor fi diferite în funcție de fișierul referitor la configurația utilizatorului sau a site-ului:

 abstract class UserResourceBase extends ResourceBase { function get_dir() { // A different file and folder for each user $user = wp_get_current_user(); return "/staticfiles/users/{$user->user_login}/"; } function get_version() { // Save the resource version for the user under her meta data. // When the file is regenerated, must execute `update_user_meta` to increase the version number $user_id = get_current_user_id(); $meta_key = "resource_version_".$this->get_filename(); return get_user_meta($user_id, $meta_key, true); } } abstract class SiteResourceBase extends ResourceBase { function get_dir() { // All files are placed in the same folder return "/staticfiles/"; } function get_version() { // Same versioning as the site, assumed defined under a constant return SITE_VERSION; } }

În sfârșit, la ultimul nivel, implementăm obiectele pentru fișierele pe care dorim să le generăm, adăugând numele fișierului, tipul fișierului și codul dinamic prin funcția get_content :

 class HeaderColorsSiteResource extends SiteResourceBase { function get_filename() { return "header-colors"; } function get_type() { return "css"; } function get_content() { return sprintf( " .site-title a { color: #%s; } ", esc_attr(get_header_textcolor()) ); } } class WelcomeUserDataUserResource extends UserResourceBase { function get_filename() { return "welcomeuser-data"; } function get_type() { return "js"; } function get_content() { $user = wp_get_current_user(); return sprintf( "window.welcomeUserData = %s;", json_encode( array( "name" => $user->display_name ) ) ); } }

Cu aceasta, am modelat fișierul ca obiect PHP. Apoi, trebuie să-l salvăm pe disc.

Salvarea fișierului static pe disc

Salvarea unui fișier pe disc poate fi realizată cu ușurință prin funcțiile native oferite de limbaj. În cazul PHP, acest lucru se realizează prin funcția fwrite . În plus, creăm o clasă de utilitate ResourceUtils cu funcții care furnizează calea absolută către fișierul de pe disc, precum și calea acestuia relativ la rădăcina site-ului:

 class ResourceUtils { protected static function get_file_relative_path($fileObject) { return $fileObject->get_dir().$fileObject->get_filename().".".$fileObject->get_type(); } static function get_file_path($fileObject) { // Notice that we must add constant WP_CONTENT_DIR to make the path absolute when saving the file return WP_CONTENT_DIR.self::get_file_relative_path($fileObject); } } class ResourceGenerator { static function save($fileObject) { $file_path = ResourceUtils::get_file_path($fileObject); $handle = fopen($file_path, "wb"); $numbytes = fwrite($handle, $fileObject->get_content()); fclose($handle); } }

Apoi, ori de câte ori sursa se schimbă și fișierul static trebuie regenerat, executăm ResourceGenerator::save trecând ca parametru obiectul care reprezintă fișierul. Codul de mai jos regenerează și salvează pe disc fișierele „header-colors.css” și „welcomeuser-data.js”:

 // When need to regenerate header-colors.css, execute: ResourceGenerator::save(new HeaderColorsSiteResource()); // When need to regenerate welcomeuser-data.js, execute: ResourceGenerator::save(new WelcomeUserDataUserResource());

Odată ce acestea există, putem pune în coadă fișierele pentru a fi încărcate prin etichetele <script> și <link> .

Punerea în coadă a fișierelor statice

Punerea în coadă a fișierelor statice nu este diferită de a pune în coadă orice resursă în WordPress: prin funcțiile wp_enqueue_script și wp_enqueue_style . Apoi, pur și simplu repetăm ​​toate instanțele obiectului și folosim un cârlig sau altul, în funcție de valoarea lor get_type() fiind fie "js" fie "css" .

Adăugăm mai întâi funcții utilitare pentru a furniza adresa URL a fișierului și pentru a spune că tipul este fie JS, fie CSS:

 class ResourceUtils { // Continued from above... static function get_file_url($fileObject) { // Add the site URL before the file path return get_site_url().self::get_file_relative_path($fileObject); } static function is_css($fileObject) { return $fileObject->get_type() == "css"; } static function is_js($fileObject) { return $fileObject->get_type() == "js"; } }

O instanță a clasei ResourceEnqueuer va conține toate fișierele care trebuie încărcate; atunci când sunt invocate, funcțiile sale enqueue_scripts și enqueue_styles vor face punerea în coadă, prin executarea funcțiilor WordPress corespunzătoare ( wp_enqueue_script și, respectiv, wp_enqueue_style ):

 class ResourceEnqueuer { protected $fileObjects; function __construct($fileObjects) { $this->fileObjects = $fileObjects; } protected function get_file_properties($fileObject) { $handle = $fileObject->get_filename(); $url = ResourceUtils::get_file_url($fileObject); $dependencies = $fileObject->get_dependencies(); $version = $fileObject->get_version(); return array($handle, $url, $dependencies, $version); } function enqueue_scripts() { $jsFileObjects = array_map(array(ResourceUtils::class, 'is_js'), $this->fileObjects); foreach ($jsFileObjects as $fileObject) { list($handle, $url, $dependencies, $version) = $this->get_file_properties($fileObject); wp_register_script($handle, $url, $dependencies, $version); wp_enqueue_script($handle); } } function enqueue_styles() { $cssFileObjects = array_map(array(ResourceUtils::class, 'is_css'), $this->fileObjects); foreach ($cssFileObjects as $fileObject) { list($handle, $url, $dependencies, $version) = $this->get_file_properties($fileObject); wp_register_style($handle, $url, $dependencies, $version); wp_enqueue_style($handle); } } }

În cele din urmă, instanțiem un obiect din clasa ResourceEnqueuer cu o listă a obiectelor PHP care reprezintă fiecare fișier și adăugăm un hook WordPress pentru a executa punerea în coadă:

 // Initialize with the corresponding object instances for each file to enqueue $fileEnqueuer = new ResourceEnqueuer( array( new HeaderColorsSiteResource(), new WelcomeUserDataUserResource() ) ); // Add the WordPress hooks to enqueue the resources add_action('wp_enqueue_scripts', array($fileEnqueuer, 'enqueue_scripts')); add_action('wp_print_styles', array($fileEnqueuer, 'enqueue_styles'));

Gata: Fiind puse in coada, fisierele statice vor fi solicitate la incarcarea site-ului in client. Am reușit să evităm tipărirea codului inline și încărcarea resurselor statice.

În continuare, putem aplica mai multe îmbunătățiri pentru câștiguri suplimentare de performanță.

Lectură recomandată : O introducere în testarea automată a pluginurilor WordPress cu PHPUnit

Gruparea fișierelor împreună

Chiar dacă HTTP/2 a redus nevoia de grupare a fișierelor, tot face site-ul mai rapid, deoarece compresia fișierelor (de exemplu, prin GZip) va fi mai eficientă și pentru că browserele (cum ar fi Chrome) au o suprasarcină mai mare care procesează multe resurse. .

Până acum, am modelat un fișier ca obiect PHP, ceea ce ne permite să tratăm acest obiect ca pe o intrare pentru alte procese. În special, putem repeta același proces de mai sus pentru a grupa toate fișierele de același tip și a servi versiunea grupată în loc de toate fișierele independente. Pentru aceasta, creăm o funcție get_content care pur și simplu extrage conținutul din fiecare resursă din $fileObjects și îl imprimă din nou, producând agregarea întregului conținut din toate resursele:

 abstract class SiteBundleBase extends SiteResourceBase { protected $fileObjects; function __construct($fileObjects) { $this->fileObjects = $fileObjects; } function get_content() { $content = ""; foreach ($this->fileObjects as $fileObject) { $content .= $fileObject->get_content().PHP_EOL; } return $content; } }

Putem grupa toate fișierele împreună în fișierul bundled-styles.css prin crearea unei clase pentru acest fișier:

 class StylesSiteBundle extends SiteBundleBase { function get_filename() { return "bundled-styles"; } function get_type() { return "css"; } }

În cele din urmă, pur și simplu punem în coadă aceste fișiere grupate, ca înainte, în locul tuturor resurselor independente. Pentru CSS, creăm un pachet care conține fișierele header-colors.css , background-image.css și font-sizes.css , pentru care pur și simplu instanțiăm StylesSiteBundle cu obiectul PHP pentru fiecare dintre aceste fișiere (și, de asemenea, putem crea JS fișier pachet):

 $fileObjects = array( // CSS new HeaderColorsSiteResource(), new BackgroundImageSiteResource(), new FontSizesSiteResource(), // JS new WelcomeUserDataUserResource(), new UserShoppingItemsUserResource() ); $cssFileObjects = array_map(array(ResourceUtils::class, 'is_css'), $fileObjects); $jsFileObjects = array_map(array(ResourceUtils::class, 'is_js'), $fileObjects); // Use this definition of $fileEnqueuer instead of the previous one $fileEnqueuer = new ResourceEnqueuer( array( new StylesSiteBundle($cssFileObjects), new ScriptsSiteBundle($jsFileObjects) ) );

Asta e. Acum vom solicita un singur fișier JS și un fișier CSS în loc de multe.

O ultimă îmbunătățire a performanței percepute implică prioritizarea activelor, prin întârzierea încărcării acelor active care nu sunt necesare imediat. Să abordăm asta în continuare.

Atribute async / defer pentru resursele JS

Putem adăuga atribute async și defer etichetei <script> , pentru a modifica momentul în care fișierul JavaScript este descărcat, analizat și executat, pentru a prioritiza JavaScript critic și pentru a împinge tot ce nu este critic cât mai târziu posibil, scăzând astfel încărcarea aparentă a site-ului timp.

Pentru a implementa această caracteristică, urmând principiile SOLID, ar trebui să creăm o nouă interfață JSResource (care moștenește de la Resource ) care să conțină funcțiile is_async și is_defer . Cu toate acestea, acest lucru ar închide ușa etichetelor <style> care în cele din urmă acceptă și aceste atribute. Deci, ținând cont de adaptabilitate, adoptăm o abordare mai deschisă: pur și simplu adăugăm o metodă generică get_attributes la interfața Resource , pentru a o menține flexibilă pentru a le adăuga la orice atribut (fie cele deja existente, fie care urmează să fie inventate) pentru ambele <script> etichete <script> și <link> :

 interface Resource { // Continued from above... function get_attributes(); } abstract class ResourceBase implements Resource { // Continued from above... function get_attributes() { // By default, no extra attributes return ''; } }

WordPress nu oferă o modalitate ușoară de a adăuga atribute suplimentare resurselor puse în coadă, așa că o facem într-un mod destul de hacker, adăugând un cârlig care înlocuiește un șir în interiorul etichetei prin funcția add_script_tag_attributes :

 class ResourceEnqueuerUtils { protected static tag_attributes = array(); static function add_tag_attributes($handle, $attributes) { self::tag_attributes[$handle] = $attributes; } static function add_script_tag_attributes($tag, $handle, $src) { if ($attributes = self::tag_attributes[$handle]) { $tag = str_replace( " src='${src}'>", " src='${src}' ".$attributes.">", $tag ); } return $tag; } } // Initize by connecting to the WordPress hook add_filter( 'script_loader_tag', array(ResourceEnqueuerUtils::class, 'add_script_tag_attributes'), PHP_INT_MAX, 3 );

Adăugăm atributele pentru o resursă atunci când creăm instanța de obiect corespunzătoare:

 abstract class ResourceBase implements Resource { // Continued from above... function __construct() { ResourceEnqueuerUtils::add_tag_attributes($this->get_filename(), $this->get_attributes()); } }

În cele din urmă, dacă resursa welcomeuser-data.js nu trebuie să fie executată imediat, o putem seta ca defer :

 class WelcomeUserDataUserResource extends UserResourceBase { // Continued from above... function get_attributes() { return "defer='defer'"; } }

Deoarece este încărcat ca amânat, un script se va încărca mai târziu, avansând momentul în care utilizatorul poate interacționa cu site-ul. În ceea ce privește câștigurile de performanță, suntem pregătiți acum!

Mai rămâne o problemă de rezolvat înainte să ne putem relaxa: ce se întâmplă când site-ul este găzduit pe mai multe servere?

Confruntarea cu mai multe servere în spatele unui echilibrator de încărcare

Dacă site-ul nostru este găzduit pe mai multe site-uri în spatele unui echilibrator de încărcare și este regenerat un fișier dependent de configurația utilizatorului, serverul care gestionează cererea trebuie, cumva, să încarce fișierul static regenerat pe toate celelalte servere; în caz contrar, celelalte servere vor servi o versiune învechită a acelui fișier din acel moment. Cum facem asta? Faptul ca serverele să comunice între ele nu este doar complex, ci se poate dovedi în cele din urmă imposibil de făcut: ce se întâmplă dacă site-ul rulează pe sute de servere, din regiuni diferite? În mod clar, aceasta nu este o opțiune.

Soluția cu care am venit este să adaug un nivel de indirectare: în loc să solicite fișierele statice de la adresa URL a site-ului, acestea sunt solicitate dintr-o locație din cloud, cum ar fi dintr-o găleată AWS S3. Apoi, la regenerarea fișierului, serverul va încărca imediat noul fișier pe S3 și îl va servi de acolo. Implementarea acestei soluții este explicată în articolul meu anterior Partajarea datelor între mai multe servere prin AWS S3.

Concluzie

În acest articol, am considerat că introducerea codului JS și CSS nu este întotdeauna ideală, deoarece codul trebuie trimis în mod repetat către client, ceea ce poate avea un impact asupra performanței dacă cantitatea de cod este semnificativă. Am văzut, ca exemplu, cum WordPress încarcă 43 kb de scripturi pentru a tipări Media Manager, care sunt șabloane JavaScript pur și ar putea fi încărcate perfect ca resurse statice.

Prin urmare, am conceput o modalitate de a face site-ul web mai rapid prin transformarea codului dinamic JS și CSS inline în resurse statice, care pot îmbunătăți stocarea în cache la mai multe niveluri (în client, Service Workers, CDN), permite gruparea în continuare a tuturor fișierelor împreună. într-o singură resursă JS/CSS pentru a îmbunătăți raportul la comprimarea ieșirii (cum ar fi prin GZip) și pentru a evita o suprasarcină în browsere de a procesa mai multe resurse simultan (cum ar fi în Chrome) și, în plus, permite adăugarea de atribute async sau defer la eticheta <script> pentru a accelera interactivitatea utilizatorului, îmbunătățind astfel timpul aparent de încărcare a site-ului.

Ca efect secundar benefic, împărțirea codului în resurse statice permite, de asemenea, ca codul să fie mai lizibil, ocupându-se de unități de cod în loc de blocuri mari de HTML, ceea ce poate duce la o mai bună întreținere a proiectului.

Soluția pe care am dezvoltat-o ​​a fost realizată în PHP și include câteva fragmente specifice de cod pentru WordPress, totuși, codul în sine este extrem de simplu, abia câteva interfețe care definesc proprietăți și obiecte care implementează acele proprietăți urmând principiile SOLID și o funcție pentru salvarea unui fișier pe disc. Cam asta e tot. Rezultatul final este curat și compact, ușor de recreat pentru orice altă limbă și platformă și nu este dificil de introdus într-un proiect existent - oferind câștiguri ușoare de performanță.