Un ghid practic pentru modulele ES6

Module ES6

Una dintre provocările majore atunci când construiți o aplicație web este cât de rapid puteți să vă extindeți și să răspundeți nevoilor pieței. Când cererea (cerințele) crește, capacitățile (funcțiile) cresc și ele. Prin urmare, este important să avem o structură arhitecturală solidă, astfel încât aplicația să crească organic. Nu dorim să ajungem în situațiile în care aplicația nu poate fi pe scară largă, deoarece tot ce este în aplicație este profund încurcat.

Scrieți un cod ușor de șters, nu ușor de extins.
- Tef, Programarea este groaznică

În acest articol, vom crea un tablou de bord simplu folosind module ES6, apoi vom prezenta tehnici de optimizare pentru a îmbunătăți structura folderului și pentru a ușura scrierea mai puțin de cod. Haideți să vedem de ce modulele ES6 sunt importante și cum să-l aplicați eficient.

JavaScript are module de mult timp. Cu toate acestea, au fost puse în aplicare prin intermediul bibliotecilor, nu construite în limbă. ES6 este prima dată când JavaScript are module (sursă) încorporate.

TL; DR - Dacă doriți să vedeți un exemplu practic în care creăm un tablou de bord folosind module ES6 dintr-un design de arhitectură, treceți la secțiunea 4.

Iată ce ne vom adresa

  1. De ce este nevoie de module ES6
  2. În zilele în care scripturile au fost încărcate manual
  3. Cum funcționează modulele ES6 (import vs export)
  4. Construim un tablou de bord cu module
  5. Tehnici de optimizare pentru exemplu
Dacă doriți să deveniți un dezvoltator web mai bun, să vă porniți propria afacere, să învățați pe alții sau să vă îmbunătățiți abilitățile de dezvoltare, voi posta sfaturi și trucuri săptămânale în ultimele limbi web.

1. De ce sunt necesare module ES6

Să vedem câteva scenarii cu privire la motivul pentru care modulele sunt relevante.

Scenariul 1 - Nu reinventați roata

În calitate de dezvoltatori, deseori recreăm lucruri care au fost deja create, fără să fim conștienți sau copiem și lipiți lucrurile pentru a reduce timpul. În final, se adaugă și ne rămâne cu numărul x de copii identice împrăștiate în toată aplicația. Și de fiecare dată când trebuie să schimbăm ceva, trebuie să o facem de x ori în funcție de câte copii avem.

Exemplu
De exemplu, imaginați-vă o fabrică de mașini încercând să reinventeze motorul de fiecare dată când a produs o mașină nouă sau un arhitect pornind de la zero după fiecare desen. Nu este imposibil să faceți acest lucru, dar atunci care este punctul de cunoaștere dacă nu puteți reutiliza experiența dobândită.

Scenariul 2 - Bariera de cunoaștere

Dacă sistemul este profund încurcat și nu există documentație, este dificil pentru dezvoltatorii vechi / noi să învețe cum funcționează aplicația și cum se conectează lucrurile.

Exemplu
De exemplu, un dezvoltator ar trebui să poată vedea care este rezultatul unei schimbări fără a ghici, altfel vom ajunge cu o mulțime de erori fără să știm de unde să începem. O soluție este de a utiliza module pentru încapsularea comportamentului, putem restrânge cu ușurință procesul de depanare și identifica rapid rădăcina problemei.

Am scris recent un articol despre „Dezvoltatorii care doresc constant să învețe lucruri noi”, cu sfaturi despre cum să îmbunătățești cunoștințele.

Scenariul 3 - Comportament neașteptat

Prin evitarea separarii preocupărilor (principiul proiectării), poate duce la un comportament neașteptat.

Exemplu
De exemplu, să zicem că cineva mărește volumul în mașină și că pornește ștergătoarele de parbriz. Acesta este un exemplu de comportament neașteptat, și nu ceva dorit în aplicația noastră.

Pe scurt, avem nevoie de module ES6 pentru a reutiliza, menține, separa și încapsula comportamentul intern de comportamentul extern. Nu este vorba de a face complexul sistemului, ci de a avea capacitatea de a scala și șterge cu ușurință lucrurile fără a rupe sistemul.

2. În vremurile în care scripturile au fost încărcate manual

Dacă ați făcut dezvoltare web de câțiva ani, atunci ați întâlnit cu siguranță conflicte de dependență, cum ar fi scripturile care nu se încarcă în ordinea corectă sau că elementele din arborele DOM nu pot fi accesate de JS.

Motivul este că HTML-ul dintr-o pagină este încărcat în ordinea în care apare, ceea ce înseamnă că nu putem încărca scripturi înainte ca conținutul din elementul să se termine.

De exemplu, dacă încercați să accesați un element din eticheta folosind document.getElementById ("id-name") și elementul nu este încărcat încă, atunci veți primi o eroare nedefinită. Pentru a ne asigura că scripturile sunt încărcate corect, putem folosi amânarea și asincronizarea. Primul se va asigura că fiecare script se încarcă în ordinea în care apare, în timp ce cel din urmă încarcă scriptul ori de câte ori devine disponibil.

Modul vechi de rezolvare a unei astfel de probleme a fost încărcarea scripturilor chiar înainte de elementul .

Dar pe termen lung, numărul de scripturi se adaugă și s-ar putea să terminăm cu 10+ scripturi în timp ce încercăm să menținem conflictele de versiune și dependență.

Separarea-a-preocupărilor

În general, încărcarea scripturilor așa cum se arată mai sus nu este o idee bună în ceea ce privește performanța, dependențele și mentenabilitatea. Nu dorim ca fișierul index.html să aibă responsabilitatea de a încărca toate scripturile - avem nevoie de un fel de structură și de separare a logicii.

Soluția constă în utilizarea declarațiilor de sintaxă, import și export ES6, o abordare elegantă și de întreținut, care ne permite să menținem lucrurile separate și disponibile doar atunci când avem nevoie.

Declarațiile de import și export

Cuvântul cheie export este folosit atunci când dorim să facem ceva disponibil undeva, iar importul este folosit pentru a accesa ceea ce exportul a pus la dispoziție.

Regula generală este că, pentru a importa ceva, trebuie să o exportați mai întâi.

Și ce putem exporta de fapt?

  • O variabilă
  • Un obiect literal
  • O clasa
  • O functie
  • ++

Pentru a simplifica exemplul așa cum se arată mai sus, putem înfășura toate scripturile un singur fișier.

Și apoi încărcați scriptul app.js în index.html. Dar mai întâi, pentru a face să funcționeze, trebuie să folosim type = "module" (sursa), astfel încât să putem folosi importul și exportul pentru a lucra cu module.

După cum puteți vedea, index.html este acum responsabil pentru un script, ceea ce facilitează întreținerea și scalarea. Pe scurt, scriptul app.js devine punctul nostru de intrare pe care îl putem folosi pentru a porni aplicația noastră.

Notă: nu aș recomanda încărcarea tuturor scripturilor într-un singur fișier, cum ar fi app.js, cu excepția celor care o necesită.

Acum că am văzut cum putem folosi declarațiile de import și export, să vedem cum funcționează atunci când lucrăm cu module în practică.

3. Cum funcționează modulele ES6

Care este diferența dintre un modul și o componentă? Un modul este o colecție de mici unități independente (componente) pe care le putem reutiliza în aplicația noastră.

Care este scopul?

  • Incapsulează comportamentul
  • Ușor de lucrat
  • Ușor de întreținut
  • Ușor de dimensionat

Da, facilitează dezvoltarea!

Deci, ce este o componentă cu adevărat?

O componentă poate fi o variabilă, funcție, clasă și așa mai departe. Cu alte cuvinte, tot ce poate fi exportat prin declarația de export este o componentă (sau o puteți numi bloc, o unitate etc.).

Ce este o componentă

Deci, ce este într-adevăr un modul?

După cum am menționat, un modul este o colecție de componente. Dacă avem mai multe componente care comunică sau pur și simplu trebuie afișate împreună pentru a forma un întreg integrat, atunci cel mai probabil aveți nevoie de un modul.

Ce este un modul

Este o provocare de a face totul reutilizabil

Un inginer principal cu peste 30 de ani de experiență în domeniul ingineriei electrice a spus odată, nu ne putem aștepta ca totul să fie reutilizat din cauza timpului, a costurilor și nu totul este menit să fie reutilizat. Este mai bine să reutilizați într-o oarecare măsură decât să vă așteptați ca lucrurile să fie reutilizate 100%.

În general, înseamnă că nu trebuie să facem totul reutilizabil în aplicație. Unele lucruri sunt menite să fie folosite o singură dată. Regula generală este că dacă aveți nevoie de ceva de mai mult de două ori, atunci poate este o idee bună să creați un modul sau o componentă.

La început, poate părea ușor să faci ceva reutilizabil, dar amintiți-vă, necesită scoaterea componentei din mediul său și așteptați-o să funcționeze într-o alta. Dar de multe ori, trebuie să modificăm părți ale acesteia pentru a o face reutilizabile pe deplin și, înainte de a o cunoaște, ai creat două componente noi.

Antoine, a scris un articol care descrie 3 reguli esențiale pentru crearea de componente JS reutilizabile, ceea ce este recomandat să citiți. Când a prezentat VueJS echipei sale, un coleg de muncă experimentat spune:

Asta este excelent, dar în experiența mea, aceste lucruri „refolosibile” nu sunt niciodată refolosite.

Ideea este că nu totul trebuie reutilizat, cum ar fi butoanele, câmpurile de intrare și casetele de verificare, etc. Întreaga treabă de a face ceva reutilizabil necesită resurse și timp și de multe ori sfârșim cu scenarii supra-gânditoare care nu s-ar produce niciodată.

CEO-ul Stack Overflow, Joel Spolsky, spune:

O soluție bună de 50% pe care oamenii o rezolvă de fapt mai multe probleme și supraviețuiește mai mult decât o soluție de 99% pe care nimeni nu o are, deoarece se află în laboratorul tău unde polițiști la nesfârșit lucrul blestemat. Transportul este o caracteristică. O caracteristică cu adevărat importantă. Produsul dvs. trebuie să îl aibă.

4. Să construim un tablou de bord cu module

Acum că avem o înțelegere de bază a modului în care funcționează modulele, să vedem un exemplu practic pe care îl vei întâlni cel mai probabil atunci când lucrezi cu cadre JS. Vom crea un tablou de bord simplu, urmând un design arhitectural care constă în machete și componente.

Codul exemplului poate fi găsit aici.

Pasul 1 - Proiectați ce aveți nevoie

În cele mai multe cazuri, dezvoltatorii ar sări direct în cod. Cu toate acestea, designul este o parte importantă a programării și vă poate economisi mult timp și dureri de cap. Amintiți-vă, designul nu ar trebui să fie perfect, ci ceva care vă conduce în direcția corectă.

Așadar, asta avem nevoie de noi pe baza designului arhitectural.

  • Componente: users.js, user-profile.js și issues.js
  • Aspecte: header.js și sidebar.js
  • Dashboard: dashboard.js

Toate componentele și aspectele vor fi încărcate în dashboard.js și apoi vom lansa bootstrap dashboard.js în index.js.

Proiectare arhitecturală a tabloului de bord

Deci de ce avem un layout și folder de componente?

Un aspect este ceva de care avem nevoie o dată, de exemplu un șablon static. Conținutul din tabloul de bord se poate schimba, dar bara laterală și antetul vor rămâne la fel (iar acestea sunt cunoscute sub denumirea de machete). Un aspect poate fi o pagină de eroare, subsol, pagina de stare și așa mai departe.

Dosarul de componente este destinat componentelor generale pe care cel mai probabil le vom reutiliza mai mult de o dată.

Este important să aveți o structură solidă la sol atunci când vă ocupați de module. Pentru a face o scară eficientă, folderele trebuie să aibă nume rezonabile care să faciliteze localizarea și depanarea lucrurilor.

Mai târziu vă voi arăta cum să creați o interfață dinamică, care necesită să aveți un spațiu de folder pentru componentele și aspectele de care avem nevoie.

Pasul 2 - Structura folderului de configurare

După cum am menționat, avem 3 foldere principale: tablou de bord, componente și machete.

- tablou de bord
- componente
- machete
index.html
index.js (punctul de intrare)

Și în fiecare fișier din interiorul folderului, exportăm o clasă.

- tablou de bord
    dashboard.js
- componente
    issues.js
    user-profile.js
    users.js
- machete
    header.js
    sidebar.js
index.html
index.js (punctul de intrare)

Pasul 3 - Implementare

Structura folderului este totul setată, deci următorul lucru este să creăm componenta (o clasă) în fiecare fișier și apoi să o exportăm. Convenția de cod este aceeași pentru restul fișierelor: fiecare componentă este pur și simplu o clasă și o metodă care consola „x component este încărcat” unde x este numele componentei pentru a indica faptul că componenta a fost încărcată.

Să creăm o clasă de utilizator și apoi să o exportăm așa cum se arată mai jos.

Observați, avem diverse opțiuni atunci când avem de-a face cu declarația de export. Deci ideea este că puteți exporta componente individuale sau o colecție de componente. De exemplu, dacă exportăm clasa, putem accesa metodele declarate prin crearea unei noi instanțe a clasei.

Bine, deci dacă te uiți la diagrama arhitecturală din pasul 1, vei observa că componenta profilului de utilizator este încapsulată de aspectul antetului. Aceasta înseamnă că atunci când încărcăm aspectul antetului, acesta va încărca și componenta profilului de utilizator.

Acum că fiecare componentă și aspect are o clasă exportată, atunci o importăm în fișierul de bord astfel:

Pentru a înțelege ce se întâmplă cu adevărat în fișierul de bord, trebuie să revizuim desenul la pasul 1. Pe scurt, deoarece fiecare componentă este o clasă, trebuie să creăm o nouă instanță și apoi să o alocăm unui obiect. Apoi folosim obiectul pentru a executa metodele așa cum se arată în metoda loadDashboard ().

În prezent, aplicația nu produce nimic, deoarece nu am executat metoda loadDashboard (). Pentru a face să funcționeze, trebuie să importăm modulul de bord în fișier index.js astfel:

Și apoi ieșirea consolei:

ES6 Componente încărcate

După cum se arată, totul funcționează și componentele se încarcă cu succes. De asemenea, putem merge mai departe și să creăm două instanțe și apoi să facem așa ceva:

Ceea ce rezultă la fel ca mai sus, dar din moment ce avem noi cazuri, obținem rezultatele de două ori.

Două instanțe unice de bord

În general, acest lucru ne permite să menținem și să reutilizăm cu ușurință modulul în fișierele necesare fără a interfera cu alte module. Creăm doar o nouă instanță care încapsulează componentele.

Cu toate acestea, după cum am menționat anterior, scopul a fost de a acoperi dinamica modului în care putem lucra cu module și componente utilizând declarațiile de import și export.

În cele mai multe cazuri, atunci când lucrăm cu cadre JS, de obicei avem o rută care poate schimba conținutul tabloului de bord. În momentul de față, totul, cum ar fi machete este încărcat de fiecare dată când invocăm metoda loadDashboard () care nu este o abordare ideală.

5. Tehnici de optimizare pentru exemplu

Acum că avem o înțelegere de bază a modului în care funcționează modulele, abordarea nu este într-adevăr scalabilă sau intuitivă când avem de-a face cu aplicații mari care constau într-o mulțime de componente.

Avem nevoie de ceva care este cunoscut sub numele de interfață dinamică. Ne permite să creăm o colecție de componente de care avem nevoie și să o accesăm cu ușurință. Dacă utilizați Visual Studio Code, IntelliSense vă arată ce componente sunt disponibile și pe care le-ați folosit deja. Înseamnă că nu trebuie să deschideți folderul / fișierul manual pentru a vedea ce componente au fost exportate.

Deci, dacă avem un modul cu douăzeci de componente, nu vrem să importăm fiecare componentă o linie după cealaltă. Pur și simplu dorim să obținem ceea ce avem nevoie și asta este. Dacă ați lucrat cu spații de nume în limbi precum C #, PHP, C ++ sau Java, veți observa că acest concept este similar în natură.

Iată ce vrem să realizăm:

După cum s-a arătat, avem mai puține linii de cod și l-am făcut declarativ fără a pierde contextul. Să vedem ce schimbări am făcut.

Creați o interfață dinamică (cunoscută și sub numele de butoaie)

O interfață dinamică ne permite să creăm o colecție de lucruri de care avem nevoie. Este ca și cum ai crea o cutie de instrumente cu instrumentele noastre preferate. Un lucru important de menționat este faptul că nu trebuie adăugată o interfață dinamică în fiecare dosar, ci la folderele care constau în multe componente.

Simplifică foarte mult importurile și le face să pară mai clare. Doar că nu dorim să avem prea multe fișiere de tip baril, deoarece acest lucru este contraproductiv și duce de obicei la probleme de dependență circulară, care uneori pot fi destul de complicate de rezolvat.
- Adrian Fâciu

Pentru a crea o interfață dinamică, creăm un fișier numit index.js care se află în rădăcina fiecărui folder pentru a reexporta un subset de fișiere sau componente de care avem nevoie. Același concept funcționează în TypeScript, doar schimbați tipul de la .js la .ts precum index.ts.

Index.js este primul fișier care se încarcă atunci când accesăm spațiul folderului rădăcină - acesta este același concept ca index.html care pornește conținutul nostru HTML. Aceasta înseamnă că nu trebuie să scriem în mod explicit importul {component} din „./components/index.js”, ci în schimb să importăm {component} de la „./components.

Iată cum arată o interfață dinamică.

Folosind o interfață dinamică, terminăm cu un nivel de rădăcină mai puțin accesibil și, de asemenea, mai puțin cod.

Creați o nouă instanță la runtime

Am eliminat cele patru instanțe din dashboard.js și am creat în schimb o instanță la runtime când fiecare component este exportat. Dacă doriți să decideți numele obiectului, puteți exporta noul Dashboard () în mod implicit, și apoi importați dashView fără bretele cretate.

După cum se arată, putem invoca direct metoda fără a fi necesară crearea unei noi instanțe și, de asemenea, scriem mai puțin cod. Totuși, aceasta este o preferință personală și puteți decide liber care este un caz de utilizare practic pentru aplicația și cerințele dvs.

Și în sfârșit, încărcăm toate componentele și aspectele cu o singură metodă.

Concluzie

Am început cu intenția de a arăta doar un scurt exemplu despre cum poți importa și exporta o componentă, dar am simțit apoi nevoia de a împărtăși tot ceea ce știu (aproape). Sper ca acest articol să vă ofere câteva informații despre cum să tratați modulele ES6 în mod eficient când construiți aplicații și despre lucrurile care sunt importante în ceea ce privește separarea preocupărilor (principiul designului).

Peste livrare:

  • Cu modulele ES6 putem reutiliza, întreține, separa și încapsula componente ușor de a fi schimbate prin comportament extern
  • Un modul este o colecție de componente
  • O componentă este un bloc individual
  • Nu încercați să faceți tot ce poate fi reutilizabil, deoarece necesită timp și resurse și, cel mai adesea, nu îl vom reutiliza
  • Creați o diagramă arhitecturală înainte de a vă scufunda în cod
  • Pentru a pune la dispoziție componentele în alte fișiere, trebuie să exportăm și apoi să importăm
  • Folosind index.js (același concept pentru TypeScript index.ts) putem crea interfețe dinamice (butoaie) pentru a accesa rapid lucrurile de care avem nevoie cu mai puțin cod și mai puține căi ierarhice
  • Puteți exporta o nouă instanță la runtime utilizând export let objectName = new ClassName ()

Vestea bună este că lucrurile s-au schimbat și ne îndreptăm spre o paradigmă bazată pe componente și reutilizabile. Întrebarea este cum putem reutiliza nu numai codul JS simplu, ci și elementele HTML într-un mod practic și intuitiv. Se pare că modulele ES6 combinate cu componente web pot să ne ofere doar ceea ce avem nevoie pentru a construi aplicații performante și scalabile.

Iată câteva articole despre care am scris despre ecosistemul web, împreună cu sfaturi și trucuri de programare personale.

  • O comparație între Angular și React
  • O minte haotică duce la un cod haotic
  • Dezvoltatori care doresc constant să învețe lucruri noi
  • Aflați aceste concepte web principale
  • Îmbunătățiți-vă abilitățile cu aceste metode importante JavaScript
  • Programează-te mai rapid prin crearea de comenzi personalizate bash

Mă puteți găsi pe Medium, unde public săptămânal. Sau mă poți urmări pe Twitter, unde postez sfaturi și trucuri relevante pentru dezvoltarea web, împreună cu povești despre devinele personale.

Dacă v-a plăcut acest articol și doriți mai multe ca acestea, vă rugăm să aplaudați (❤) și să le împărtășiți cu prietenii sau colegii, este o karma bună.