Node.js i npm
Konobar koji ne stoji uz stol dok kuhinja radi, jezik za formice postaje backend, i jedan Schlueterov registar postaje najveća hrpa tuđeg koda na svijetu.
Godina je 2009. Ako radiš na serveru — pravom, ozbiljnom, onom koji vrti webshop ili banku — pišeš Javu. Ili PHP, ako si siromašniji rod. Možda Ruby, ako si hipster s bradom, u vrijeme prije nego što je brada postala obavezna. Sve troje imaju jednu zajedničku, nepisanu istinu, toliko duboko usvojenu da je nitko ne izgovara naglas: kad zahtjev stigne, dodijeliš mu nit — zamisli nit kao jednog radnika kojeg zadužiš za jednog gosta, i koji dok taj gost čeka ne radi ništa drugo. Ta nit ode do baze podataka, pita je nešto, i onda čeka. Stoji. Spava. Ništa ne radi, samo drži mjesto u redu i troši memoriju dok se baza ne probudi i odgovori. Ako ti stigne tisuću zahtjeva odjednom, imaš tisuću radnika koji spavaju odjednom. Server ne radi ništa pametnije od konobara koji, čim primi narudžbu, sjedne za stol i čeka da se pizza ispeče — a onda se čudi zašto mu je restoran pun praznih stolica i gladnih ljudi na vratima.
S druge strane te ograde stoji JavaScript — jezik koji radi u pregledniku i brine se o onome što korisnik vidi i klika (tome se kaže „frontend”), dok se s druge strane, na serveru, odvija „backend” — dio koji čuva podatke i radi pravi posao. JavaScript je nastao da pomiče slikice po ekranu i provjerava je li netko upisao e-mail bez znaka @. Frontend ljudi ga pišu jer moraju — bira ga preglednik, ne oni. Backend ljudi ga gledaju kao stariji brat koji gleda mlađega kako upravo jede blato: s mješavinom sažaljenja i prezira. Jezik za formice. Igračka. Ne nešto na čemu se pušta ozbiljan sustav koji drži novac ili zdravstvene kartone. Ta hijerarhija — frontend dolje, backend gore, i debela crta između — postoji otkad je struka struka, a 2009. je, čini se, uklesana u kamen dublje nego ikad.
Onda jedan čovjek, Ryan Dahl, stane na binu jedne konferencije i pokaže nešto što na prvi pogled izgleda kao trik za zabavu. Server napisan u JavaScriptu koji, dok čeka odgovor baze podataka, ne spava. Ne dodjeljuje mu se nit koja samo stoji i troši dah. Umjesto toga, poručuje: javi mi kad odgovor stigne, ja ću u međuvremenu poslužiti sljedećih deset tisuća ljudi. Nema čekanja. Nema spavanja. Jedna jedina traka za posluživanje, ali ta traka nikad ne staje.
Vratari struke, naravno, to neće prihvatiti bez borbe. Ali borba je, kao i svaka borba protiv demokratizacije u ovoj knjizi, izgubljena već u trenutku kad je počela — samo to još nitko na toj binici 2009. ne zna. Ovo se već jednom dogodilo u povijesti softvera — kompajler je preuzeo posao koji su prije radili ljudi rukom. Ovo je isto, samo malo drukčije obučeno: sad će frontend developer pisati i backend, i pritom se, začudo, neće srušiti ništa što nije trebalo srušiti.
Zamisli restoran. Jedan jedini konobar, cijela smjena. Ali ovaj konobar ne stoji uz tvoj stol dok ti kuhinja sprema odrezak — to bi bilo idiotski, umro bi od gladi dok on tupo gleda u vrata kuhinje čekajući da zazvoni zvonce. Ne. Ovaj konobar uzme narudžbu, baci je kuhinji i odmah ide do sljedećeg stola. I sljedećeg. I sljedećeg. Kad kuhinja završi tvoj odrezak, zazvoni, konobar ga donese i nastavlja dalje. Jedan čovjek, tisuću stolova, nitko ne čeka njega, on ne čeka nikoga. To je, ako hoćeš cijelu poentu u jednoj slici, Node.js.
Taj isti model niti-koje-čekaju vrijedio je za sve do 2009. — svaki gost svog konobra, koji stoji uz stol i ne radi ništa dok kuhinja ne zazvoni.
Ono što je Dahl tada pokazao imalo je i mehanizam iza sebe: jedna nit, cijela smjena, i nikad ne stoji besposleno — jer čim nešto krene čekati (bazu, disk, mrežu), taj posao se odloži u stranu, konobar ide dalje raditi nešto korisno, a kad čekanje završi, netko ga pikne i on se vrati po rezultat. To odlaganje i vraćanje ima ime — event loop — i cijela filozofija Node.js-a stoji na njemu. Ne brže po zadatku. Više zadataka odjednom, s manje ljudi. Ekonomija konobara, ne brzina jednog serviranja.
Ali ta genijalna ideja — ne čekaj, radi dalje, javi se kad završiš — ima cijenu. Kako javiš „gotovo” nekome tko čeka? U ranom JavaScriptu odgovor je bio: callback. Funkcija koju daš kao argument i koja se pozove kad posao završi. Zvuči elegantno dok imaš jedan takav poziv. Problem nastaje kad ti treba pet stvari zaredom — pročitaj datoteku, pa spoji se na bazu, pa pošalji mail, pa zapiši log, pa odgovori korisniku — i svaka čeka prethodnu. Kod se počne uvlačiti udesno kao stepenice, funkcija u funkciji u funkciji u funkciji, sve dublje, dok ne dobiješ nešto što programeri s pravom zovu callback hell. Ne metafora. Pravi, dokumentirani pakao, s krivudavim zagradama umjesto vatre.
Prvo su stigla obećanja — Promises — da će posao jednom završiti, s lijepim, plosnatim lancem umjesto uvučenih stepenica. Zatim, 2017., stiže async/await, sintaksa koja izgleda kao da je kod običan, linearan, kao da se čita od gore prema dolje i kao da nigdje ne čeka, dok ispod haube event loop marljivo radi svoj posao, žonglirajući tisuću stolova odjednom. Tri koraka, jedan cilj: da programer napiše nešto što izgleda kao spora, sinkrona misao, a da ispod toga sve trči brzo i paralelno, kao da nikad nije ni čekalo.
To je, u malom, cijela civilizacijska priča ovog poglavlja: nešto skalamerjeno u žurbi (Dahl je Node sklepao za tek nekoliko mjeseci), izgrađeno na tuđem motoru — V8, Googleov JavaScript engine koji je inače stvoren za Chrome i čiji je jedini posao pretvoriti JavaScript kod u brzi mašinski jezik koji procesor razumije, poklon koji Google nikad nije planirao da će završiti negdje drugdje — popravljano u hodu dok je već u produkciji milijuna servera. I baš zato što je bilo brzo, prljavo i praktično — funkcioniralo je. A onda su svi ti frontend developeri koje su vratari zanata tapšali po glavi shvatili jednu stvar koja će za par godina promijeniti cijelo tržište rada: jezik kojim su pisali dropdown menije mogao je odjednom pokretati i server ispod njih.

npm: paket za sve
Dok se svijet čudio da server pisan u JavaScriptu ne pada u nesvijest nakon prvog zahtjeva, jedan je čovjek rješavao problem koji je zvučao dosadno, a bio je sudbonosan: kako sve te sitne komadiće koda, koje ljudi pišu za Node, dovesti do drugih ljudi bez slanja ZIP datoteke e-mailom. Zove se Isaac Z. Schlueter, i ako je Dahl otac Node.js-a, Schlueter je taj koji mu je sagradio kuhinju, ostavu i dostavnu službu u jednom. Napisao je npm — node package manager — 2010., i u tom trenutku, iako to tada nitko nije mogao znati, upravo je posijao najveći repozitorij koda u povijesti čovječanstva. Ne šalim se, ne pretjerujem, nema navodnika ironije. Najveći. Ikad.
Ideja je bila jednostavna do banalnosti: umjesto da svaki programer iznova piše istu funkciju koja radi neku sitnicu, netko to napiše jednom, objavi na registar, i svi ostali samo upišu jednu naredbu — npm install — i gotovo. Paket stigne, uvučen u tvoj projekt, spreman za rad. Zvuči kao sitnica. Bila je sitnica koja je promijenila kako se piše softver, jer je odjednom trošak dijeljenja pao na skoro ništa.
I ljudi su navalili. Ne stotinama paketa, ne tisućama — milijunima. Danas npm registar hostira preko dva milijuna paketa, i ta brojka je toliko velika da postaje glupa: to je više paketa nego što ih imaju svi ostali programski jezici svijeta zajedno, uključujući i one koji postoje duže od JavaScripta. PyPI, Maven Central, RubyGems, CPAN — zbroji ih sve, i npm ih još nadmašuje. Registar koji je trebao riješiti problem dijeljenja koda postao je, u jednom trenutku, veći od svih drugih rješenja tog istog problema, zbrojenih zajedno.
Ali tu dolazi obrat koji je manje slavan od brojke, a mnogo govori o duhu vremena: kad imaš registar u kojem je objavljivanje paketa besplatno, brzo i bez ikakvog nadzora kvalitete, dobiješ svašta. Ozbiljne, korisne biblioteke koje rade posao kompleksnih sustava — da. Ali i pakete čija je jedina funkcija provjeriti je li broj paran ili neparan. Da, čitaš dobro. Paket koji se zove is-odd radi upravo to: primi broj, vrati ti true ili false (dakle, samo „da” ili „ne”) — jednu jedinu liniju koda koju bi napisao i student na prvom satu programiranja. I taj paket, taj apsurd u obliku funkcije, skida se stotine tisuća puta tjedno.
Ali ta šala, koliko god zvučala kao anegdota za zabavu na konferenciji, simptom je nešto ozbiljnijeg. Kad je instaliranje paketa jeftinije od pisanja pet redaka koda — a psihološki, jest, jedna naredba nasuprot pet minuta razmišljanja — ljudi počinju instalirati prije nego što misle. Zašto bih razbijao glavu oko toga kako dopuniti string s lijeve strane nekim znakom (recimo, da broj „7” pretvorim u „007”, ono što bi svaki urar ili blagajnik radio ručno) kad postoji paket koji to učini za mene? I sad, umjesto pet redaka koda koje si napisao i razumiješ, imaš tuđi paket, koji povlači svoje ovisnosti (dakle, druge pakete o kojima on ovisi da bi radio), koje povlače svoje ovisnosti, sve do dna koje nitko nije vidio.
To „instaliraj-prvo-misli-poslije” nije greška u kulturi npm-a — to je danas defaultni način na koji se piše JavaScript, uzduž i poprijeko, od hobi-projekata do enterprise sustava koji obrađuju novac. I ako ti se to sad čini nevažnim, kao usputna crta u priči o demokratizaciji programiranja, zapamti tu misao. Vratit ćemo joj se, i puno prije nego bi pomislio, jer ta ista navika ima repove koji dosežu daleko dalje od jedne provjerene parnosti broja.

Full-stack JavaScript
E sad dolazimo do trenutka kad se cijela ova priča prestane vrtiti oko servera i počne vrtiti oko tebe, developeru, i tvog egzistencijalnog pitanja: moram li stvarno znati tri jezika da bih napravio jednu prokletu web stranicu? Do Node.js-a odgovor je bio da. Frontend je JavaScript, htio ti se to sviđalo ili ne. Backend je bio Java, PHP, Ruby ili C#, birao si po ukusu i po tome tko ti plaća račune. Baza je SQL, jer baza je uvijek SQL. Tri jezika, tri mentalna sklopa, tri seta grešaka koje pamtiš napamet. A onda se, negdje oko 2012., u glavama gomile developera upalilo isto svjetlo: čekaj, ako Node.js znači da mogu pisati server u JavaScriptu... zašto ne bih *sve* pisao u JavaScriptu?
I tako je nastao MEAN stack — MongoDB, Express, Angular, Node — akronim koji zvuči kao ime neke bezvezne boy bend grupe, ali koji je zapravo prva ozbiljna demonstracija da cijela aplikacija, od baze podataka do gumba koji čovjek klikne, može biti napisana u jednom jeziku. MongoDB sprema podatke u formatu koji nalikuje na JavaScript objekt, umjesto u tablicama kakve pamtiš iz klasičnih SQL baza. Express je taj tanki sloj servera o kojem smo pisali. Angular (i uskoro cijela vojska njegovih rođaka — React, Vue) je frontend, ono što čovjek vidi i klika. Node je ljepilo koje sve to spaja. Jedan jezik, od baze do preglednika. Zvuči kao sitnica. Nije.
Zašto je to bilo toliko veliko? Zato što je srušilo ulaznu barijeru u struku na razinu koju povijest informatike nije vidjela otprilike nikad. Prije Node.js-a, da postaneš »full-stack developer«, morao si naučiti minimalno dva jezika, dva ekosustava, dvije filozofije grešaka koje te bude u tri ujutro. To je posao, to traje, to traži nekoga tko te plaća dok učiš, ili fakultet koji te muči četiri godine. Poslije Node.js-a? Naučiš JavaScript — jedan jezik, doduše onaj isti kojeg su backend inženjeri prezirali kao »jezik za formice« — i legalno možeš aplicirati na poziciju koja u nazivu ima riječ »full-stack«. Bootcamp od dvanaest tjedana, malo muke, malo Stack Overflowa, i evo te u industriji koja plaća bolje od gotovo svega osim, možda, onkologije.
I to nije marketing, to su brojke — bootcamp generacija koja se u ta dva-tri godišta pojavila na tržištu rada i stvarno se zaposlila, u nemalom broju baš zahvaljujući tome što je JavaScript postao jedini jezik koji im je trebao od životopisa do prve produkcijske greške. Startupi su to prigrlili prvi, i s razlogom: mali tim od troje ljudi koji svi znaju isti jezik može se preseljavati s fronta na back i obrnuto po potrebi, bez čekanja da se »onaj koji znade backend« vrati s godišnjeg. Za firmu s malo love i puno ambicije, to je razlika između toga da lansira proizvod za tri mjeseca ili za devet.
Ali — i ovo »ali« nije zlobno, ovo je pošteno — svaka demokratizacija ima svoju cijenu, i ovdje su cijenu platile dvije stvari. Prva je jezična raznolikost. Kad je sve napisano u istom jeziku, cijeli tvoj sustav dijeli i iste slabosti tog jezika, iste rupe u sigurnosnom modelu, iste bugove u istom runtimeu (onom istom V8-u koji sve to pokreće ispod haube). Monokultura je u poljoprivredi opasna zato što jedna bolest može pokositi cijelo polje — u softveru je logika identična, samo je bolest paket s malicioznim kodom umjesto plamenjače.
Druga cijena, ona koju stariji inženjeri vole naglasiti uz pivo i uz onaj poseban prizvuk glasa koji znači »ja sam ovo radio kad je bilo teško«, jest dubina. I tu treba biti pošten prema obje strane, jer oboje imaju pravo. Netko koji je naučio backend kroz dvanaest tjedana bootcampa vjerojatno ne razumije baze podataka onako kako ih razumije čovjek koji je pet godina radio administraciju produkcijskog SQL servera — one nevidljive mašinerije koja čuva sve podatke firme i ne smije pasti, jer ako padne, pada i cijela tvrtka s njom. Ne razumije mrežne slojeve (nevidljive cjevovode kojima podaci putuju od jednog računala do drugog), ne razumije zašto ti server curi memoriju u tri ujutro — a to je, u prijevodu za normalne ljude, kad program polako troši sve više radne memorije i ne vraća je, kao slavina koja kaplje cijelu noć dok ti spremnik za vodu ne prelije kuhinju. »Full-stack« developer, kažu ti stariji s podignutom obrvom, često znači »pola-stack, dvaput« — malo frontenda koje površno poznaje, malo backenda koje površno poznaje, i nula onog dubokog znanja koje se stječe kad godinama gledaš isti sustav kako se lomi na isti način.
Tako je full-stack JavaScript postao ono što jest: ne savršeno rješenje, nego iskreno demokratsko rješenje — otvorilo je vrata cijeloj generaciji ljudi koja bez njega ne bi ni pokucala, po cijeni da neki od njih nikad ne saznaju što se krije iza tih vrata na dubljoj razini. A negdje u pozadini, dok se cijela ta priča o pristupačnosti odvija, jezik koji je nastao za deset dana kao pomoć za validaciju formi tiho postaje jedini jezik koji treba znati da bi radio bilo gdje u toj kući, od podruma do krova.

Enterprise prihvaća igračku
Do 2014. Node više nije bio igračka koju frontend developeri nose na sastanke kao dokaz da su i oni ozbiljni ljudi. Postao je alat kojim se rješavaju problemi koji koštaju stvarne novce, u firmama koje ne trpe eksperimente samo zato što su cool. Tu spadaju i takozvane »enterprise« tvrtke — veliki, konzervativni igrači poput banaka, telekoma i velikih korporacija, kojima ispad sustava ne znači ljutog korisnika na forumu, nego novinski naslov i sudske tužbe. A kad takav enterprise nešto prihvati, ne prihvati ga zbog priče — prihvati ga zbog brojki.
Netflix je prvi ozbiljno zapeo u tu priču. Njihova stranica za pokretanje aplikacije — ono što vidiš prije nego što uopće stigneš do filma — izgrađena je dobrim dijelom u Nodeu, a rezultat je bio da se vrijeme pokretanja skratilo za oko 70 posto. Ne zato što je Node magičan, nego zato što posao koji je radio (skupljanje podataka s desetaka servisa i slaganje stranice od toga) točno odgovara filozofiji event loopa. Puno čekanja, malo računanja — baš ono što Netflixu treba. LinkedIn je krenuo istim putem s mobilnim backendom i migraciju sažeo u jednu rečenicu koja je obletjela konferencije: isti posao, deset puta manje strojeva. Walmart je testirao Node na prometu za Black Friday, dana kad svaka sekunda kašnjenja direktno briše prodaju, i preživio. To nisu benchmarkovi na blogu nekog entuzijasta — to su firme koje bi mirno vratile stari sustav da ih je novi osramotio pred milijunima kupaca.
I baš kad se činilo da priča ide ravno prema sretnom završetku — enterprise usvaja, svi zarađuju, kraj — Node je uspio zajebati stvar na način koji je bio čisto njegov. Joyent, mala firma iz Silicijske doline koja je u tom trenutku de facto »posjedovala« Node (plaćala razvoj, drži autorska prava na ime, odlučuje što ide u sljedeću verziju), počela je kočiti s objavljivanjem novih verzija V8 motora, jer nova verzija znači posao, a posao znači rizik za velike korisnike koji ne žele da im se nešto pokvari preko noći. Dio zajednice, poglavito ljudi iz frakcije io.js, pomislio je — dobro, ako vi kočite, mi ćemo sami. I napravili su fork (kopiju cijelog projekta na koju više ne pazi izvorni vlasnik, nego oni koji su ga preuzeli). Isti kod, drugo ime, brži ritam objavljivanja, i, što je bilo ključno, upravljanje odlukama koje nije ovisilo o hiru jedne firme.

Ekosustav kao dostignuće i dug
Sjećaš se Douga McIlroya iz prve knjige? Onaj tip iz Bell Labsa koji je 1968. sanjao o softverskim komponentama kao ciglama — uzmeš gotovu, uklopiš je, gradiš dalje, nitko više ne piše sortiranje od nule. Cijela struka je tu ideju gledala kao lijepu utopiju, negdje pored leta na Mars. E pa, dogodila se. Samo ne u C-u, ne u nekom akademskom projektu s državnim novcem — dogodila se u jeziku koji je Brendan Eich sastavio u deset dana 1995. godine, u žurbi da Netscape Navigator, tadašnji najpopularniji preglednik, dobije nešto, bilo što, za animirane mišiće na webu. Taj jezik zove se JavaScript, i to je njegov cijeli rodni certifikat — napisan za vikend, bez vremena za filozofiranje o lijepim apstrakcijama. npm je, bez šale, najveća biblioteka dijeljenog koda u povijesti softvera. Preko dva milijuna paketa, brojka koja raste dok ovo čitaš, i sve to postoji zahvaljujući jeziku koji je nastao kao žurna zakrpa. McIlroy bi se, vjerujem, nasmijao. Ili zaplakao. Vjerojatno oboje.
Konkretno: napraviš prazan projekt, samo da isprobaš jednu jedinu biblioteku za, recimo, formatiranje datuma. Instaliraš. npm ti izbaci poruku: added 247 packages. Dvjesto četrdeset sedam. Za formatiranje datuma. Otvoriš mapu node_modules, uđeš unutra kao Alisa u zečju rupu, i tu je cijela civilizacija — paketi koje je netko napisao, netko drugi o njima ovisi, treći ovisi o tom drugom, i tako u dubinu koju nitko normalan ne prati do kraja. Tvoj hello-world, taj bezazleni ispis jedne rečenice na ekranu, u pozadini povlači stotine tuđih odluka, tuđih bugova, tuđih trenutaka nepažnje u tri ujutro. I ti to sve — uvoziš. Bez ugovora, bez garancije, bez ičega osim vjere da onaj koji je napisao paket »is-odd« (da, postoji paket koji provjerava je li broj neparan, i ne, ne šalim se, i da, skida ga stotine tisuća ljudi tjedno) neće jednog dana promijeniti mišljenje.
A radi se, moraš priznati, o čudnom ugovoru. Netko negdje, često anoniman, često nikad plaćen ni centa, održava komadić koda o kojem ovisi pola interneta. Nema odbora koji ga nadzire, nema tvrtke koja garantira da će taj paket sutra još postojati u istom obliku. On to radi iz ljubavi, iz dosade, iz osjećaja odgovornosti — ili, sve češće, iz umora koji polako prelazi u bijes.
I sad, na kraju ovog poglavlja, dok si zadovoljan što razumiješ event loop, npm registar i zašto je pola Silicijske doline odjednom postalo full-stack — postavimo pitanje koje bi svaki dobar pripovjedač postavio prije nego zatvori knjigu za noć: što se točno dogodi kad jedan od tih anonimnih ljudi, jednog običnog jutra, iz ljutnje ili principa, odluči povući sav svoj kod s interneta?