Aceasta este povestea unui proiect al meu. Una mare. Un amestec între PHP și Node.js. Este o aplicație cu o singură pagină dintr-un punct de vedere și un site SEO optimizat de la altul. Au fost scrise tone de JavaScript, CSS și HTML. Într-un singur cuvânt, un cosmar de spaghete pentru orice dezvoltator. Au existat căderi și înălțimi. Producerea și rezolvarea de bug-uri. Luptând cu cele mai noi tehnologii și terminând cu o bibliotecă simplă, care este subiectul acestui articol.
Așa cum se întâmplă în mod normal, proiectul a fost considerat nu atât de mare. Am intrat în discuție, am discutat despre modul în care va fi gestionată dezvoltarea, ce tehnologii vor fi folosite și cum le vom folosi. Am făcut un plan și am ajuns să lucrăm. La început am avut câteva pagini, controlate de un CMS. Nu a fost atât de mult cod JavaScript la început, deoarece sistemul nostru a furnizat cea mai mare parte a conținutului.
Iată o structură brută a proiectului:
Am pus codul nostru de client în directoare diferite. Codul de pe server a fost doar PHP în acest moment, așa că a intrat în php
director. Am împachetat totul în aproximativ 30 de fișiere și totul a fost OK.
În perioada de câteva luni, am încercat concepte diferite și am schimbat codul proiectului de mai multe ori. Din punct de vedere actual, am putut observa patru mari probleme pe care le-am întâlnit.
Se pare că clientul a fost mulțumit de rezultat și a decis să investească mai mult în aspectul său de Internet. Am fost rugați să construim câteva caracteristici noi. Unele dintre ele erau doar noi locuri de conținut, altele erau adăugiri la paginile deja existente. Am început să adăugăm tot mai multe fișiere în toate folderele de mai sus. A început să se încurce puțin, așa că am decis să creăm subdirectoare pentru diferitele pagini și să salvăm codul necesar acolo.
De exemplu, stilurile CSS pentru despre pagina au fost în css / despre / styles.css
. JavaScript în js / despre / scripts.js
si asa mai departe. Am folosit un script PHP care concatenă fișierele. Au existat, desigur, părți ale site-ului care au fost pe mai multe pagini și le-am pus comun
directoare. Acest lucru a fost bine pentru un timp, dar nu a funcționat bine pentru mult timp, deoarece atunci când directoarele s-au umplut, a fost greu să modifice ceva. A trebuit să căutați trei directoare diferite pentru a găsi ceea ce aveați nevoie. Site-ul a fost încă în principal scris în PHP.
În acel moment, aplicațiile mobile au devenit populare. Clientul dorea ca site-ul său să fie disponibil pentru dispozitivele mobile și acesta este punctul de cotitură important în proiect. A trebuit să transformăm site-ul într-o aplicație cu o singură pagină. Și nu numai că a trebuit să aibă multe caracteristici în timp real. Desigur, nu tot conținutul site-ului trebuia încărcat dinamic. SEO a fost încă o parte importantă a viziunii clientului. Am ales stiva MEAN pentru părțile viitoare. Problema era cu paginile vechi. Conținutul lor a trebuit să fie deservit de PHP, dar logica paginilor sa schimbat și a fost făcută complet cu JavaScript. Timp de câteva săptămâni am simțit călătorii de la Titanic. Ne-am grăbit să eliberăm ceva, dar a existat o gaură după gaură și foarte curând, nava noastră era plină de apă (bug-uri).
Am folosit GruntJS pentru o vreme, dar am migrat la Gulp. A contribuit foarte mult pentru că am crescut viteza de dezvoltare. Cu toate acestea, a fost încă prea enervant să adăugați sau să modificați componentele existente. Arhitectura solidă pe care am avut-o la început a fost transformată într-un amestec complex de fișiere. Da, au existat convenții stricte de numire și plasare a acestor fișiere, dar era încă prea dezordonat. Apoi, am lovit capul împreună și am venit cu următorul format:
Am împărțit site-ul în diferite componente, care erau ca niște cutii negre. Locuiesc în dosarul propriu. Tot ceea ce se referă la componentă a fost salvat în directorul său. Am proiectat cu atenție API-urile claselor. Au fost testabile și comunicabile. Am constatat că o structură cum ar fi aceasta a funcționat mai bine pentru noi deoarece am avut tone de module independente. Da, amestecăm fișierele JavaScript cu stiluri CSS și șabloane HTML, dar a fost mai ușor să lucrăm pe bază de unități, în loc să săpăm adânc în mai multe directoare.
Paginile care erau vechi și pe care trebuia să le trimitem prin intermediul PHP, erau de asemenea pline de logică JavaScript. Cu toate acestea, în unele cazuri, Angular nu a funcționat foarte bine. A trebuit să facem mici hack-uri pentru a face lucrurile să meargă fără probleme. Am ajuns cu un amestec între controlerele unghiulare și codul personalizat. Vestea bună a fost că bugetul proiectului a fost extins și am decis să ne folosim propriul cadru. În acel moment, am fost în curs de dezvoltare propriul meu preprocesor CSS. Proiectul merge într-adevăr, foarte repede. Foarte curând mi-am pornit biblioteca pentru a folosi clientul. Linia de linie a fost transformată într-un cadru restrâns, pe care am început să îl integrăm în proiect.
Aceasta este probabil ceea ce cereți. Ei bine, există o duzină de alții care oferă o gamă largă de capabilități. Da, este adevărat, dar ... nu aveam nevoie de o gamă largă de capabilități. Aveam nevoie de lucruri specifice și nimic mai mult. Am fost gata să acceptăm faptul că prin utilizarea unui cadru popular, putem adăuga câteva kilobyte la sarcina globală a paginii. Aceasta nu era o mare problemă.
Statutul codului nostru a fost problema. Ne-am concentrat pe construirea unei arhitecturi bune și suntem cu toții de acord că uneori soluția personalizată se potrivește mai bine. Utilizarea Angular, Ember, Knockout sau Backbone vine cu beneficiile sale, dar adevărul este că nu există un cadru universal.
Îmi place cuvintele lui Jeremy Keith, în discursul său "Puterea Simplității", a spus că cel mai important lucru în alegerea instrumentului tău este filozofia persoanei care a făcut instrumentul și dacă această filozofie se aliniază cu a ta. Dacă ideile cadrului nu se aliniază cu a voastră, foarte curând, veți merge împotriva lor. Același lucru sa întâmplat și cu noi. Am încercat să folosim Angular și am avut prea multe dificultăți. Probleme pe care am reușit să le rezolvăm, dar am folosit hack-uri și soluții complexe.
Am încercat, de asemenea, Ember, dar nu a funcționat, deoarece se bazează în mare măsură pe mecanismele sale de rutare. Coloana vertebrală a fost o alegere frumoasă și a fost cel mai apropiat lucru pentru viziunea noastră. Cu toate acestea, când am introdus AbsurdJS am decis să o folosim.
AbsurdJS a fost inițial inițiat ca un preprocesor CSS, extins la un preprocesor HTML și a fost porționat cu succes pentru utilizarea clientului. Deci, la început le folosim pentru compilarea JavaScript în HTML sau CSS. Da, m-ai auzit bine; am început să scriem stilurile și marcajele în JavaScript (probabil că sună ciudat, dar vă rugăm să continuați să citiți). Am împins biblioteca înainte și au fost adăugate o duzină de funcționalități.
Când aveți un sistem complex, cu multe pagini, într-adevăr nu doriți să rezolvați mari probleme. Este mult mai bine să împărțiți totul în sarcini mai mici și să le rezolvați unul câte unul. Am făcut același lucru. Am hotărât ca aplicația noastră să fie construită din componente mai mici, cum ar fi:
var absurd = Absurd (); var MyComp = absurd.component ('MyComp', constructor: function () // ...); var instanță = MyComp ();
absurd.component
definește o clasă. Apelarea MyComp ()
metoda creează o nouă instanță.
Având toate aceste mici componente, am avut nevoie de un canal de comunicare. Modelul de observator a fost perfect pentru acest caz. Deci, fiecare componentă este un dispecer de evenimente.
var MyComp = absurd.component ('MyComp', doSomething: function () this.dispatch ('ceva-se întâmplă');); var instanță = MyComp (); example.on ('something-happen', funcția () console.log ('Hello!');); instance.doSomething ();
De asemenea, suntem capabili să transmitem datele împreună cu mesajul. Definiția componentelor și natura lor "ascultă-expediere" este destul de banală. Am adoptat acest concept din celelalte cadre populare, pentru că arată natural. De asemenea, a fost mult mai ușor pentru colegii mei să înceapă să utilizeze AbsurdJS.
Împreună cu marcarea PHP servită, am creat dinamic elemente DOM. Aceasta înseamnă că avem nevoie de acces la elementele DOM existente sau la cele noi, care vor fi adăugate mai târziu în pagină. De exemplu, să presupunem că avem următorul cod HTML:
Titlul paginii
Lorem ipsum dolor stați amet, consectetur adipiscing elit.
Iată o componentă care preia titlul:
absurd.component ('MyComp', html: '.content h1', constructor: function () this.populate (); console.log (this.el.innerHTML); // Titlul paginii) ();
popula
metoda este singura magie în întreaga bibliotecă. Ea face mai multe lucruri cum ar fi compilarea CSS sau HTML, leagă evenimente și astfel de lucruri. În exemplul de mai sus, se vede că există o html
de proprietate și inițializează el
care indică elementul DOM. Acest lucru funcționează destul de bine pentru noi, deoarece odată ce am primit această referință, am reușit să lucrăm cu elementele și copiii săi. Pentru acele componente care au nevoie de elemente create dinamic, html
proprietatea acceptă un obiect.
absurd.component ('MyComp', html: 'div.content': h1: 'Titlul paginii', p: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. .populate (); document.querySelector ('body'); appendChild (this.el);) ();
JSON de mai sus este tradus la același marcaj HTML. Am ales JSON deoarece, din punct de vedere al JavaScript, este mult mai flexibil. Suntem capabili să fuzionăm obiecte, să le înlocuim sau să ștergem numai părți din ele. În majoritatea cadrelor populare, șabloanele sunt doar text simplu, ceea ce le face dificil de manipulat. AbsurdJS are, de asemenea, propriul motor templating.
absurd.component ('MyComp', html: 'div.content': h1:<% this.title %>', ul: ['<% for(var i=0; i', li: '<% this.availableFor[i] %>','<% %>'], titlu:' Asta e minunat ', disponibil pentru: [' toate browserele ',' Node.js '], constructor: function () this.populate (); document.querySelector ( 'organism') appendChild (this.el.); ) ();
Rezultatul este:
Asta-i grozav
- toate browserele
- Node.js
acest
în expresiile de mai sus, indică componenta în sine. Codul între <%
și %>
este JavaScript valid. Deci, caracteristici precum proprietățile computerizate ar putea fi ușor dezvoltate direct în definirea șablonului. Desigur, putem folosi același motor de șablon cu marcajul deja existent. De exemplu:
<% this.title %>
<% for(var i=0; i<this.availableFor.length; i++) %>
- <% this.availableFor[i] %>
<% %>
... poate fi controlat cu următoarea componentă (rezultatul este același):
absurd.component ('MyComp', html: '.content', titlu: 'That's awesome', availableFor: ['toate browserele', 'Node.js'], constructor: function ();) ();
Oricum, punctul este că am reușit să definim șabloane sau să le creăm de la zero. De asemenea, putem controla datele injectate într-un mod ușor și natural. Totul este doar proprietățile obiectului bun vechi JavaScript.
Am împărțit cu succes întregul sistem în module mici. Părțile care erau în fața controlorilor angulare au devenit componente AbsurdJS. Am realizat că codul HTML a fost strâns legat de definiția lor, fapt care a schimbat complet gestionarea marcajului în aplicație. Am încetat să ne gândim la concatenare, convenții sau așa ceva. Nu trebuia să creați deloc fișiere HTML. Când mă uit înapoi, am putut vedea acest moment exact în istoria comiterii noastre. Este ușor de vizibil deoarece multe fișiere au fost eliminate din baza de cod.
Apoi m-am gândit, ce se va întâmpla dacă facem același lucru cu CSS. Desigur, a fost posibil deoarece AbsurdJS era un preprocesor CSS și putea produce CSS. Tocmai am primit șirul compilat, creăm un nou stil
etichetă în cap
din pagina curentă și o injectați acolo.
absurd.component ('MyComp', css: '.content': h1: culoare: '# 99FF00', padding: 0, margin: 0, p: fontSize: 20px : '.content', constructor: function () this.populate ();) ();
Aici este stil
eticheta care este produsă:
Iar din zi în zi am transferat stilurile CSS din fișierele SASS (pentru că, la un moment dat, am ales SASS ca un preprocesor CSS) către componentele AbsurdJS. Pentru a fi sincer, a fost destul de ușor deoarece toate mixurile și variabilele pe care le avem au fost definite ca funcții și variabile JavaScript. Schimbul de stiluri a fost mai ușor pentru că totul a fost Javascript.
... când totul funcționează perfect, dar simțiți că ceva nu este în regulă
Ne uitam la cod. A mers. AbsurdJS a condus chiar și părțile vechi. Noul lucru folosește aceeași bibliotecă. HTML și CSS au fost bine separate și plasate direct în definiția componentelor. Cu toate acestea, am simțit că era ceva în neregulă. M-am oprit o vreme și m-am întrebat: "De ce este făcut Webul?".
Și ceea ce am făcut, este puțin diferit. Seamănă mai mult cu imaginea de mai jos.
Am construit site-uri pentru mai mult de zece ani și îmi amintesc momentele când am luptat cu toții pentru separarea mare a acestor trei materiale de construcție. Și ceea ce am făcut în acest proiect este exact opusul. Nu exista nici un fișier CSS și HTML (aproape). Totul a fost JavaScript.
Mulți oameni vor spune că acest lucru este ridicol și ar trebui să-i dăm banii clientului înapoi. Da, ar putea fi adevărat, dar acest concept a funcționat perfect în cazul nostru. Nu am scris o cerere. De fapt, am scris o grămadă de componente independente. Cred că Web-ul va fi o combinație de componente gata de utilizare.
Noi, ca dezvoltatori, vom trebui să dezvoltăm astfel de componente și, probabil, să le conectăm și să folosim astfel de componente scrise de alții. Proiecte precum AbsurdJS sau Polymer arată că acest lucru este posibil și vă încurajez să experimentați în această direcție.
Deci, în cele din urmă, afacerea clientului a mers bine. A fost atât de bun încât a decis să lanseze un nou serviciu. Si ghici ce. El dorea ca anumite părți ale aplicației existente să fie transferate în noul proiect. Nu vă pot spune cât de fericiți am fost să mutăm componente dintr-un loc în altul. Nu am fost nevoiți să configurați ceva, să copiați marcajul HTML sau fișierele CSS. Tocmai am primit fișierul JavaScript al componentei, l-am plasat undeva și am creat o instanță a acesteia. A funcționat doar pentru că nu există dependențe. Nu aș fi surprins dacă unele dintre aceste componente sunt puse în vânzare foarte curând. Ele sunt destul de ușoare și oferă o funcționalitate plăcută legată de produsul clientului.
Da, am încălcat câteva reguli. Reguli cu care eu personal sunt de acord. Reguli pe care le-am urmat de mai mulți ani. Cu toate acestea, realitatea este că toți vrem calitatea și uneori că calitatea este accesibilă încălcând regulile. Vrem să producem un cod bun, bine structurat, ușor de întreținut, flexibil și extensibil. Nu vrem să ne uităm înapoi și să spunem: "Oh, Doamne, asta a fost scris de mine!". Când mă uit înapoi acum, știu de ce codul arată așa cum face. Se pare că pentru că a fost scris pentru acest proiect în mod specific.
Dacă ați găsit acest tutorial interesant, verificați pagina oficială a lui AbsurdJS. Există ghiduri, documentație și articole. Puteți încerca chiar și biblioteca online. Ca orice alt instrument, AbsurdJS este proiectat pentru utilizare specifică. Se potrivește bine pentru proiectul nostru și poate fi potrivit pentru dvs. Nici măcar nu o numesc cadru, pentru că nu-mi place această definiție. Este mai mult ca un set de instrumente, mai degrabă decât un cadru complet de stivă. Simțiți-vă liber să experimentați cu el, să faceți cereri de tragere sau să transmiteți probleme. Este complet open-source și disponibil la GitHub.