În acest articol, aș dori să prezint un exemplu de standardizare a unui toolchain JavaScript, care s-a dovedit a fi practic într-un mediu enterprise de mare amploare, ce conține mii de proiecte. Exemplul descris se referă doar la partea de frontend a aplicațiilor.
În acest context, prin toolchain ne referim la totalitatea de biblioteci și frameworkuri folosite pentru: linting de cod, formatarea codului, pre-commit hooks, teste unitare, teste end-to-end etc. într-un proiect frontend.
În special, vreau să subliniez avantajul de a avea un set standardizat de unelte pentru toate proiectele versus un set atipic, adaptat unui singur proiect.
Dacă spunem "automobil hypercar", care tinde să bată recorduri de viteză, ne imaginăm un automobil construit pentru performanță, foarte scump, cu o producție foarte limitată. Sunt mașinării grozave, dar pentru omul de rând este mai relevant un automobil produs de o marcă de încredere, în serie, la un preț accesibil, pentru care se pot găsi piese de schimb în orice moment, iar procesul de service este lin.
Aceeași comparație doresc să o fac în cazul proiectelor frontend. Da, putem face ceva extrem de bine croit pentru performanță, folosind cele mai "umflate gogoși" dintre biblioteci, alese după entuziasmul de moment. Dezavantajele în această situație pot fi: programatori nișă, greu de găsit, iar tehnologiile folosite având riscul de a fi abandonate de proprii dezvoltatori.
Alternativa ar fi "mașina de producție" a proiectelor frontend: un lanț de unelte ales conservator, automatizări și standarde de cod "bătute în cuie", care ajută procesul de bootstrapping al unui proiect.
Această schemă reprezintă nu o serie de recomandări, ci un sistem stratificat, unde fiecare strat este dependent de cel precedent:
Stratul 1: Dezvoltare - Angular (framework), ESLint + Stylelint (linting), Prettier (formatting), Jest / Vitest (unit tests), bibliotecă internă de componente.
Stratul 2: Calitate cod și commit
Husky + lint-staged (pre-commit), commitlint (impune Conventional Commits), Sonar (code quality).
Stratul 3: E2E Testing
Playwright.
Stratul 4: CI / CD
GitHub Actions (CI/CD workflows), platformă internă cloud bazată pe Kubernetes, Sonatype Nexus (repository management).
Dacă React domină prin popularitate (~80 mil. descărcări săptămânale pe npm vs. ~19 mil. pentru Angular), Angular oferă o propunere de valoare diferită pentru dezvoltarea la scară mare.
Angular este un framework, nu o bibliotecă. Vine la pachet cu un sistem CLI, routing, sistem de formulare, client HTTP, dependency injection, sistem de componente și sistem de server-side rendering.
Pentru organizații care mențin sute sau chiar mii de aplicații, structura "opinionated" a Angular devine un avantaj. Fiecare proiect urmează aceeași arhitectură și același mod de lucru.
Deși Angular are o "curbă de învățare" mai abruptă, structura completă a pachetului oferit aduce beneficii majore în ceea ce privește consistența și mentenabilitatea pe termen lung.
Descrierea alegerilor din acest toolchain
ESLint + Stylelint + commitlint: "poarta" în trei straturi, care asigură un standard consistent de cod.
Prettier: elimină dezbaterile și asigură un singur stil de cod în toate proiectele.
Husky + lint-staged: rulează automat regulile de consistență a codului înainte de un commit.
Jest / Vitest: Jest oferă maturitate și o comunitate considerabilă, iar Vitest este un competitor nou care oferă o viteză (pun intended!) accelerată și, recent, a fost selectat de echipa Angular ca motor oficial de unit testing.
Playwright: platformă de testare E2E, cross-platform, headless și headed, compatibilă cu TypeScript.
Sonatype Nexus: repository privat de pachete. Asigură securitate și control asupra dependențelor (npm) ale proiectelor.
La nivel de BMW Group, pe lângă un toolchain bine definit, menținem și o listă de "practici bune" standard: convenții documentate pentru arhitectură, tipare de testare, cerințe de securitate și proceduri de deployment. Acest ghid evoluează alături de alegerile noastre tehnologice, fiind adaptat din lecțiile învățate în nenumărate proiecte.
Standardizând practicile bune, ne asigurăm că echipele nu "reinventează roata", iar informațiile legate de probleme precedente sunt centralizate.
Un alt aspect ce ține de menținerea practicilor bune este să rămânem la curent cu ultimele schimbări în tehnologie. Spre exemplu, revoluția Angular începând cu versiunea 17, care a introdus reactivitatea bazată pe signals. Acest lucru a creat un ecou și în biblioteci precum NgRx, care au dezvoltat soluții bazate pe signals pentru state management, aliniindu-se la noua direcție a ecosistemului Angular.
Toate aceste lucruri trebuie luate în calcul și adoptate treptat ca "practici bune". Altfel, riscăm să rămânem în urmă.
Argumentul pentru toolchainuri standardizate are la bază o observație simplă: fiecare proiect configurat personalizat se consideră unic, dar majoritatea se confruntă cu probleme identice.
O echipă care personalizează un nou proiect poate petrece săptămâni cercetând, dezbătând și implementând schimbări pe care organizații mai mature le-au rezolvat acum ani de zile.
Toolchainurile standardizate rezolvă acest tipar păgubos. Se răspunde la probleme recurente o singură dată, documentând rațiunea, iar răspunsurile sunt puse direct într-o infrastructură pe care toate echipele o moștenesc.
Sistemul poate părea o constrângere, dar este un avantaj imens, în special în câștigarea celei mai valoroase resurse: timpul. O echipă care începe cu un lanț de instrumente deja proiectat se poate concentra pe problema reală: livrarea de funcționalități în aplicații.
În loc să rezolve același puzzle de fiecare dată, echipa beneficiază de experiențele colective care au ajustat toolchainul și practicile bune de cod.