ABONAMENTE VIDEO REDACȚIA
RO
EN
NOU
Numărul 150
Numărul 149 Numărul 148 Numărul 147 Numărul 146 Numărul 145 Numărul 144 Numărul 143 Numărul 142 Numărul 141 Numărul 140 Numărul 139 Numărul 138 Numărul 137 Numărul 136 Numărul 135 Numărul 134 Numărul 133 Numărul 132 Numărul 131 Numărul 130 Numărul 129 Numărul 128 Numărul 127 Numărul 126 Numărul 125 Numărul 124 Numărul 123 Numărul 122 Numărul 121 Numărul 120 Numărul 119 Numărul 118 Numărul 117 Numărul 116 Numărul 115 Numărul 114 Numărul 113 Numărul 112 Numărul 111 Numărul 110 Numărul 109 Numărul 108 Numărul 107 Numărul 106 Numărul 105 Numărul 104 Numărul 103 Numărul 102 Numărul 101 Numărul 100 Numărul 99 Numărul 98 Numărul 97 Numărul 96 Numărul 95 Numărul 94 Numărul 93 Numărul 92 Numărul 91 Numărul 90 Numărul 89 Numărul 88 Numărul 87 Numărul 86 Numărul 85 Numărul 84 Numărul 83 Numărul 82 Numărul 81 Numărul 80 Numărul 79 Numărul 78 Numărul 77 Numărul 76 Numărul 75 Numărul 74 Numărul 73 Numărul 72 Numărul 71 Numărul 70 Numărul 69 Numărul 68 Numărul 67 Numărul 66 Numărul 65 Numărul 64 Numărul 63 Numărul 62 Numărul 61 Numărul 60 Numărul 59 Numărul 58 Numărul 57 Numărul 56 Numărul 55 Numărul 54 Numărul 53 Numărul 52 Numărul 51 Numărul 50 Numărul 49 Numărul 48 Numărul 47 Numărul 46 Numărul 45 Numărul 44 Numărul 43 Numărul 42 Numărul 41 Numărul 40 Numărul 39 Numărul 38 Numărul 37 Numărul 36 Numărul 35 Numărul 34 Numărul 33 Numărul 32 Numărul 31 Numărul 30 Numărul 29 Numărul 28 Numărul 27 Numărul 26 Numărul 25 Numărul 24 Numărul 23 Numărul 22 Numărul 21 Numărul 20 Numărul 19 Numărul 18 Numărul 17 Numărul 16 Numărul 15 Numărul 14 Numărul 13 Numărul 12 Numărul 11 Numărul 10 Numărul 9 Numărul 8 Numărul 7 Numărul 6 Numărul 5 Numărul 4 Numărul 3 Numărul 2 Numărul 1
×
▼ LISTĂ EDIȚII ▼
Numărul 106
Abonament PDF

Migrarea funcționalităților frontend de la monolit la microfrontenduri

Vlad Luca
Senior Frontend Developer @ PitechPlus



Andrei Bajenaru
Mid Frontend Developer @ PitechPlus



PROGRAMARE


O cerință cu care cel mai probabil mulți dintre noi am avut tangențe deja, sau dacă nu, cel mai probabil vom avea în viitor, este migrarea unor funcționalități deja existente spre o tehnologie de actualitate. În cele ce urmează vom prezenta acele funcționalități care pentru noi au făcut o astfel de migrare relevantă. Dar mai întâi să vedem care este contextul inițial. În cazul nostru, scopul a fost migrarea funcționalităților dintr-o aplicație monolit: componenta backend a migrat spre microservicii, iar cea frontend către microfrontenduri. Obiectivul nostru este acela de a prezenta provocările întâmpinate pe parcurs și în același timp soluțiile pe care le-am ales.

Conceptul de "aplicație monolit"- definit mai simplu - reprezintă o aplicație software în care funcționalitățile de frontend și cele de backend sunt dezvoltate în același codebase. În cazul nostru plecăm de la o aplicație Model - View - Controller (MVC) scrisă în PHP cu Laravel framework, partea de frontend fiind implementată cu blade templates și jQuery. Pentru a exemplifica cele anterior menționate, în diagrama de mai jos este reprezentată structura unei aplicații monolit clasice.

Ce sunt microfrontendurile

Conceptul de microserviciu este unul cu care majoritatea dintre noi cred că suntem familiarizați, însă când vine vorba de microfrontend lucrurile stau puțin diferit. Ideea de microfrontend a început să prindă putere în ultimii ani, dar încă nu este abordată la o scară largă. Practic, acest concept își propune să aducă beneficiile asociate microserviciilor într-o aplicație de frontend. Cel mai întâlnit mod de a dezvolta aplicații frontend în ultima perioadă este acela de a construi un single page application (SPA), dezvoltat de o echipă de frontend, specializată. Problemele care pot apărea dacă utilizăm acest mod de dezvoltare al aplicației sunt în general legate de dimensiunea codebase-ului care poate să devină greu de întreținut. O astfel de aplicație poate fi numită "frontend monolit". În ceea ce privește scopul nostru inițial, acesta este să folosim o tehnologie de actualitate și să ne îndepărtăm pe cât posibil de noțiunea de monolit. Important de menționat este faptul că echipa noastră este formată din aproximativ 100 de programatori care, până în momentul în care a fost luată în calcul rescrierea, lucrau simultan pe același codebase. Principiul care stă la baza microfrontend-urilor este modul de organizare al aplicației: fiecare echipă este responsabilă de câte un subdomeniu din businessul aplicației. Alte idei care stau la baza acestei abordări se referă la stackul de tehnologii folosit pentru dezvoltare. Practic, fiecare echipă are libertatea de a decide ce și cum folosește, fără a fi nevoie de o coordonare în prealabil cu celelalte echipe implicate în proiect, fiecare trebuind să dezvolte aplicații independente, atât pe partea de backend cât și pe partea de frontend, aplicații care nu se bazează de exemplu pe variabile globale, shared state etc. În figura de mai jos putem observa organizarea echipelor atunci când se lucrează cu microfrontenduri, precum și modul în care componentele comunică între ele.

De ce a fost necesară o astfel de migrare?

Unul dintre principalele argumente în favoarea migrării dintr-un codebase monolitic într-o aplicație microfrontend îl reprezintă existența dependențelor vechi care nu se mai bucură de o mentenanță activă. Printre aceste dependențe putem, fără doar și poate, să includem librăria jQuery. Putem afirma faptul că folosirea jQuery este indicată în cazul proiectelor de dimensiuni mici, de prezentare, care nu necesită o manipulare complexă a DOM-ului sau care nu au o funcționalitate complexă astfel încât să nu fie nevoie de procesări costisitoare. În cazul nostru, proiectul a crescut într-un mod alert, iar odată cu el și dificultatea funcționalităților dezvoltate, motiv pentru care am început să simțim limitările stackului tehnologic existent. Astfel, migrarea către microfrontenduri bazate pe un framework de JavaScript, React în cazul nostru, ne ajută să eliminăm codul legacy și în același timp ne oferă mult mai multe posibilități pentru dezvoltarea funcționalităților noi, întrucât React se bucură de o popularitate tot mai mare și de o comunitate foarte activă. Dacă analizăm graficul următor, putem observa foarte clar tendința utilizatorilor de a renunța la jQuery ca dependență în proiecte. Graficul reprezintă popularitatea căutărilor pe Google a termenilor "jQuery" și "React", valoarea 100 reprezentând popularitatea maximă a termenului, iar valoarea 50 arătând că popularitatea a scăzut la jumătate din cea maximă înregistrată.

Un alt motiv pentru care migrarea dinspre monolit spre aplicații microfrontend poate fi benefică este reprezentat de dificultatea pe care o presupune mentenanța unui codebase monolitic. În cazul în care pe proiectul respectiv lucrează mai multe echipe, există un risc ridicat de apariție a codului duplicat deoarece specificațiile de design sunt cel mai probabil aceleași pentru toate echipele, fiind foarte greu de identificat existența unor elemente comune deja dezvoltate astfel încât acestea să poată fi reutilizate. În unele cazuri, chiar dacă un astfel de element comun este disponibil, modul în care codul este organizat poate face imposibilă utilizarea lui, fără a recurge la duplicare.

Practic, mutând una sau mai multe funcționalități în unul sau mai multe microfrontenduri, ne asigurăm că fiecare microfrontend are propria responsabilitate pentru o anumită parte din aplicație, funcționând independent de celelalte, ușurând astfel mentenanța. În cazul nostru, un alt element care s-a dovedit a fi benefic este reprezentat de dezvoltarea unei librării de componente reutilizabile care poate fi utilizată de toate echipele în microfrontendurile lor. Librăria respectivă cuprinde componente precum: dropdownuri, form fielduri, popupuri și alte componente necesare pentru implementarea funcționalităților în cadrul mai multor echipe.

Întrucât o aplicație monolit presupune existența unui număr mare de funcționalități, acestea trebuie acoperite de teste funcționale. În cazul nostru acestea lipseau cu desăvârșire, fapt ce constituie un risc, în special în situațiile în care aplicația se află într-un continuu proces de dezvoltare. Pentru noi, migrarea spre o tehnologie de actualitate a însemnat o foarte bună oportunitate pentru implementarea testelor funcționale și odată cu ele creșterea nivelului de încredere și siguranță din cadrul echipei.

Workflowul migrării

Prima problemă de care ne-am lovit încă înainte de a decide care va fi stackul tehnologic spre care vom migra, a fost găsirea unui workflow care să ne satisfacă nevoile. Deoarece aplicația pe care lucrăm este live și are câteva zeci de mii de utilizatori activi în fiecare zi, suntem conștienți de faptul că, pe lângă migrarea funcționalităților, va trebui în continuare să asigurăm și mentenanța în monolit. Dar acest lucru nu ne va permite alocarea întregii echipe doar pe taskurile aferente migrării. Odată cu rescrierea funcționalităților era necesară și modificarea designului interfeței și uneori modificarea funcționalităților astfel încât să satisfacă cât mai bine nevoile utilizatorilor. Acest lucru a dus la decizia de a folosi feature flaguri pentru release-uri, pentru ca modificările în platforma live să poată fi efectuate gradual. Inițial, acestea se realizează doar pentru o parte din utilizatori, astfel încât să putem colecta feedback și să putem remedia posibilele probleme în cazul în care acestea apar înainte de a face release pentru 100% din utilizatori. Un alt element important în procesul de migrare a fost definirea ordinii în care funcționalitățile urmează a fi migrate, scopul final fiind migrarea codului în proporție de 100%. După cum am menționat anterior, în cazul nostru nu a fost posibilă alocarea întregii echipe doar pentru rescrierea funcționalităților. De aceea, am decis să începem progresiv prin implementarea unor mici părți funcționale și independente dintr-o pagină sau identificarea elementelor comune care apar pe mai multe pagini și construirea unor componente reutilizabile, care ulterior urmau să fie incluse în monolit.

Includerea unei componente din microfrontend în monolit a constat în adăugarea unui div în HTML-ul paginii în care avem nevoie, div pe care am adăugat după nevoie data-attributes pentru a face disponibile unele date care la momentul respectiv erau accesibile doar din monolit. Acest mod de a transmite date este unul temporar, dar necesar, și ne ajută să decuplăm frontendul de implementarea microserviciilor pe backend. Spre exemplu, în imaginea de mai jos avem un div cu id-ul "microfrontend-main-container" care va fi folosit pentru a identifica elementul în care urmează a fi randată componenta de React din microfrontend.

<div id="microfrontend-main-container"
     data-position-name="{{$positionName}}"
     data-language="{{$currentLocale}}"/>

Cum funcționează?

Vă întrebați cum anume decide microfrontendul ce anume trebuie să randeze în divurile incluse în fișierele din monolit? În timpul buildului, microfrontendul generează un fișier JavaScript și un fișier CSS care urmează să fie incluse în monolit, în fișierele în care avem nevoie de componentele din microfrontend. În cazul nostru, în fișierele blade în care trebuie să includem microfrontendul, trebuie adăugate următoarele scripturi:

<link rel="stylesheet" href="{{$mfeCss}}">
<script src={{$mfeJs}}></script>

Astfel, fișierele generate de microfrontend sunt incluse în pagini și suntem cu un pas mai aproape de a avea componentele randate din microfrontend în monolit. În situația noastră, fișierele care se generează la build din microfrontend sunt încărcate în cloud și servite printr-un microserviciu de către monolit. Apoi acestea sunt incluse în pagini conform scripturilor anterior prezentate.

Totodată, pentru ca microfrontendul să decidă ce anume să randeze într-un anumit div, acesta folosește un sistem bazat pe events, practic din monolit se face dispatch la un custom event care conține o cheie pe baza căreia microfrontendul, care implementează event listenerul, randează componenta corespunzătoare. Spre exemplu, putem avea situații în care mesajul primit de microfrontend îi transmite acestuia că trebuie să randeze o anume componentă în cazul în care pagina nu este în totalitate migrată sau situația în care avem un mesaj generic iar microfrontendul va randa componentele pe baza rutei curente.

Concluzie

Poate cel mai mare beneficiu rezultat în urma rescrierii funcționalităților, pentru noi ca echipă, este nivelul de încredere pe care-l avem în codul dezvoltat. Începând cu un codebase pe care nu-l cunoșteam și care nu beneficia de teste funcționale, eram în punctul în care orice modificare însemna un risc mare de regresii, indiferent de cât de bine reușeam să ne testăm munca. În același timp, posibilitatea ca modificările noastre să influențeze unele funcționalități dezvoltate de către alte echipe, asupra cărora noi să nu avem vizibilitate, era ridicată. Prin migrarea spre microfrontenduri și microservicii am reușit să ajungem în punctul în care fiecare echipa care lucrează la proiect să devină independentă, iar acesta este un aspect foarte important mai ales când numărul echipelor este considerabil și se află într-o continuă creștere. Un alt mare beneficiu este reprezentat de faptul că am reușit să eliminăm librăriile outdated din proiect, acestea devenind un impediment de fiecare dată când era necesară dezvoltarea unor noi funcționalități. Utilizarea unei tehnologii up to date, care se bucură de mentenanță constantă și de o comunitate activă, ne oferă multiple posibilități în implementarea noilor funcționalități ceea ce reprezintă un factor important când vine vorba de gradul de satisfacție al membrilor echipei.

Un alt aspect, la fel de important ca cele deja menționate, îl reprezintă gradul de satisfacție al clientului care acum dispune de o aplicație mult mai sigură, rata de buguri raportate fiind într-o continuă scădere, direct proporțională cu numărul de funcționalități pe care reușim să le migrăm. Dar cel mai mare avantaj este că oferă clientului o aplicație mult mai ușor de dezvoltat pe viitor, fără constrângeri de ordin tehnic.

NUMĂRUL 149 - Development with AI

Sponsori

  • Accenture
  • BT Code Crafters
  • Accesa
  • Bosch
  • Betfair
  • MHP
  • BoatyardX
  • .msg systems
  • P3 group
  • Ing Hubs
  • Cognizant Softvision
  • Colors in projects