Przejdź do treści

Zapachy świeżej kawy: node.js

Choć zamiast kawy piję herbatę, to nawiązując do tytułu naszej strony chciałbym rozpocząć mały cykl artykułów o świeżości. Świeżości, która bije z innowacyjnych, rozwojowych, małych (albo większych) projektów/technologii. Świeżości, która jest szczególnie potrzebna osobom, które od dłuższego czasu siedzą w jednym temacie, projekcie, środowisku. Nawet jeśli narzędzia / rozwiązania, które będę starać się opisywać nie znajdą bezpośredniego rozwiązania w twojej pracy… to jednak samo ich zapoznanie i zrozumienie może dać dużo frajdy i ogólnie przyczynić się do rozwoju. No więc do dzieła. Czas na pierwsze łyki świeżej kawy, która dzisiaj serwuje nam projekt node.js i okolice.

Co to jest node.js? Krótka definicja ze strony projektu mówi: „Evented I/O for V8 JavaScript”. O co chodzi? W skrócie, ktoś wziął silnik Javascriptowy V8 od Google i obudował tak, aby był niezależnym interpreterem – trochę podobnym do Ruby, Pythona itd. Na tej bazie zbudowano dość proste, ale potężne API do tworzenia aplikacji sieciowych (głównie, ale nie tylko, web) zgodnie z duchem „event-driven„.

Co to daje? Po pierwsze architektura „sterowania przez zdarzenia” jest od zupełnych podstaw asynchroniczna. Zdarzenia mogą zdarzać się w dowolnym czasie, w dowolnej kolejności i dowolnej ilości. Jeśli tylko mamy wolne zasoby, to obsługujemy zdarzenia gdy tylko się pojawią. A gdy się nie pojawiają to nie robimy nic. Pomysł pozornie prosty, ale konsekwencje jego wprowadzenia mogą być znaczne. Lepsze wykorzystanie zasobów – szczególnie wielordzeniowych procesorów, lepsza separacja kodu i mityczne „loose coupling” – czyli luźne powiązanie komponentów – to tylko niektóre z korzyści. Ale oczywiście nic nie przychodzi za darmo – trzeba się przestawić na trochę innych sposób myślenia i programowania (i być może to jest główna korzyść jaką wyniesiemy interesując się bliżej projektem node.js).

Po drugie mamy Javascript. O ile budujemy aplikacje web, to jest szansa, że po stronie klienta będziemy uruchamiać nasz kod Javascriptowy. Dzięki node.js również po stronie serwera będzie działać Javascript. Taka unifikacja pozwala na łatwiejsze współdzielenie kodu i usuwanie duplikacji logiki, która może występować z konieczności implementacji – chociażby pewnych walidacji – dwa razy.

Co więcej Javascript uruchamiany na współczesnych silnikach (które już dawno przestały być zwykłymi interpreterami, które czytają kod linia po linii i próbują wykonać) takich jak V8, jest super wydajna. I nie jest to bynajmniej głos marketingowy. V8 działa trochę podobnie do HotSpot znanego z JVM od Suna (obecnie Oracle) w tak zwanej wersji „server”. Kod Javascript jest kompilowany do kodu maszynowego przez szybki kompilator JIT, następnie następuje proces ciągłego profilowania (obserwowania) kodu i stosowania dalszych optymalizacji wybranych (często używanych lub wyraźnie powolnych) fragmentów. Jeśli dana optymalizacja nie prowadzi do wzrostu wydajności może zostać wycofana i zastąpiona inną (tzw. deoptymalizacja). Wśród optymalizacji znajdziemy wiele typowych technik – między innymi usuwanie martwego kodu, agresywne „in-linowanie”, czyli „wklejanie” ciała funkcji w miejsce jej wywołań, rozwijanie pętli, czyli przewidywanie rozgałęzień (branch-prediction) tak aby z wyprzedzeniem przewidzieć wartość warunków logicznych i dostarczyć odpowiedni kod bez skoków. Oczywiście zarządzanie pamięcią oparte jest o wydajną implementację zbieracza śmieci (garbage collector).

Nigdy nie byłem wielkim fanem Javascriptu jako takiego – więc tym bardziej, uczciwie muszę przyznać, że w ostatnich latach chyba nic innego w IT nie przyspieszyło tak bardzo jak silniki Javascriptowe. Z resztą walka między twórcami Chrome, Firefox, IE oraz Opera o tytuł najszybszego browsera jest fascynując – każda kolejna wersja to wzrost wydajności mierzony w dziesiątkach a czasem setkach procent! Jeśli mimo tego co się działo, ktoś ma wątpliwości czy Javascript daje możliwość pisania naprawdę wydajnych aplikacji, to polecam zobaczyć chociażby to: q3bsp w przeglądarce wspierającej WebGL.

Tyle o motywacji – chociaż trzeba przyznać, że to zdecydowanie nie wszystkie zalety i nie całe piękno node.js. Ale resztę zostawiam Wam do odkrycia samemu. Przejdźmy do krótkiego opisu samego środowiska.

Sama bazowa instalacja node.js jest dość prosta i z pudełka daje całkiem sympatyczną „bibliotekę standardową”. Prosta – minimalna aplikacja webowa napisana w node.js wygląda tak:
[crayon lang=”javascript”]
require(’http’).createServer(function (req, res) {
res.writeHead(200, {’Content-Type’: 'text/plain’});
res.end(’Hello World\n’);
}).listen(1234, „127.0.0.1”);
[/crayon]

Po uruchomieniu tego kodu możemy połączyć się z adresem http://localhost:1234 i zobaczyć piękny napis Hello World. Przykład jest na tyle prosty, że nie pokazuje jeszcze niczego. Spróbujmy teraz sprawić, że przy każdym obsłużonym zapytaniu nasz serwer wpisze coś do logów (na wyjście standardowe). Moglibyśmy dodać to do ciała funkcji obsługującej requesty, ale nie po to mamy środowisko event-driven. Funkcje powinny być możliwie proste i jednozadaniowe! Zamiast tego, po prostu przypniemy nową funkcje, która zajmie się logowaniem:
[crayon lang=”javascript”]
var server = require(’http’).createServer(function (req, res) {
res.writeHead(200, {’Content-Type’: 'text/plain’});
res.end(’Hello World\n’);
})

server.on(’request’, function(req) { console.log(’Processing request, url = ’ + req.url) })

server.listen(1234, „127.0.0.1”)
[/crayon]

Proste? Moim zdaniem tak. I to tego działa, przynajmniej u mnie :)

Teksty na naszym blogu z założenia nie mają być podręcznikami programowania ani instrukcjami step-by-step jak napisać swoją super aplikacji, dlatego po więcej przykładów i szczegółowy opis API dostępnego w node.js odsyłam oczywiście do całkiem niezłej dokumentacji dostępnej w sieci.

Od początku naszej przygody programistycznej z node.js, warto zinteresować się bogatym ekosystemem frameworków napisanych w node.js. Co ciekawe, mimo że projekt jest relatywnie młody, to zasoby gotowe do użycia są potężne i obszerne. Aby trochę to wszystko ogarnąć powstało nawet dedykowane narzędzie npm, czyli menadżer pakietów dla node. Obecnie w oficjalnym repozytorium npm mamy już ponad 3700 pakietów!

Tak bogate repozytorium z pewnością nie ułatwia wyboru :) Warto poczytać wiki projektu i ogólnie to co mówi „lud” żeby wyczuć co jest warto uwagi przynajmniej na początek. Mój głos w tej sprawie brzmi Express (w końcu przyda się nam dobry ekspres do kawy): expressjs.com. Framework urzeka prostotą i zarazem bogactwem, a przykłady aplikacji wykonanych za jego pomocą robią wielkie wrażenie: expressjs.com/applications.html. Polecam!

Jeśli jesteś obecnie deweloperem aplikacji web w dowolnej technologii to zapewne znasz chociażby podstawy języka Javascript. Mając tą wiedzę i zasoby dostępne w ramach świata node.js z łatwością będziesz w stanie wystartować prostą aplikację. Idąc dalej być może zauważysz piękno i bogactwo tkwiące w prostocie dostępnych narzędzi. Prawdziwe odświeżające doświadczenia dla ludzi borykających się na co dzień z potworami w stylu Websphere, Weblogic czy IIS+ASP.NET.

A jeśli komuś byłoby mało awangardy, w ramach node można programować również w innych językach programowania! Jak to działa? Skoro Javascript jest taki super szybki (a jest) to ludzie zaczęli pisać kompilatory/interpretery innych popularnych języków, które w wyniku swojego działania emitują Javascript.

Zaczynając od opcji egzotycznych – istnieje backend do LLVM, który wypluwa z siebie Javascript. Znaczy to, że możemy kompilować kod C/C++ do Javascript i uruchamiać go w przeglądarce albo w node. I to działa! Nie wierzysz? No to: github.com/kripken/emscripten/wiki.

Kolejną, nieco normalniejszą :) ciekawostką jest: move – prosty, funkcyjny (ho, ho) język programowania, który można użyć w node. Super lekka, przyjazna składnia – może nie jakoś wyjątkowo odkrywcze czy nowe, ale po prostu działa.

Coraz większą popularność zyskuje inny język: Coffee Script. Na stronie projektu bardzo ładnie pokazano co zyskujemy w porównaniu do zwykłego Javascriptu – w skrócie jest krócej i jaśniej.

Na tym kończym pierwszy odcinek. Zachęcam do weekendowej albo chociaż wieczornej lektury na temat node.js, npm, express, move i coffeescriptu. Kto wie, może dzięki temu uda się postawić jakąś fajną aplikację w kilka chwil? Jeśli tak to koniecznie pochwalcie w komentarzach! Powodzenia.

W następnym odcinku zapachu świeżej kawy, o ile nie wpadnie na mnie nic ciekawszego, zajmiemy się frameworkiem Play. Zapraszam.

Update: Już po opublikowaniu tego artykułu, całkiem przypadkiem znalazłem w sieci inicjatywę Node Knockout, czyli 48-godzinny konkurs dla programistów aplikacji node.js. Więcej info tu: http://nodeknockout.com/. Konkurs odbył się pod koniec sierpnia – wyniki ogłoszono kilka dni temu. Warto zapoznać się z aplikacjami, które wygrały i ogólnie zobaczyć ile da się zrobić w 48 godzin kiedy naprawdę jest ciśnienie :) Mi szczególnie spodobał się projekt Chess@Home: http://sylvainzimmer.com/2011/09/06/chessathome-building-largest-chess-ai/ w ramach którego powstała aplikacja z AI do gry w szachy, działająca na klastrze, do którego dołączone są wszystkie komputery wchodzące na stronę projektu! Twórcy, po wygraniu w jednej z kategorii Node KO idą dalej i chcą pobić rekord Guinessa w kategorii największy klaster z AI szachowym:) Obecny rekord wynosi 2070 węzłów. Czy uda się go pobić? Zobaczymy :) Swoją drogą chłopaki (pewnie nie jako pierwsi) wpadli na ciekawy pomysł wykorzystania mocy obliczeniowej komputerów klienckich odwiedzających stronę www. Ciekawe czy za jakiś czas google będzie dorzucać jednego javascripta więcej na swoje strony, który użyje Twój komputer do przetwarzania searchy :) albo do łamania szyfrów dla CIA… albo na odwórt do łamania CIA:) Ciekawe czasy…

5 komentarzy do “Zapachy świeżej kawy: node.js”

  1. Wracam do tego posta jakiś rok po przeczytaniu, bo był dla mnie pewnego rodzaju inspiracją. Teraz mogę się wypowiedzieć z perspektywy zdobytego doświadczenia w tej technologii:)

    Node.js rozwija się bardzo dynamicznie, w ciągu kilku lat powstało ponad 160 tysięcy pakietów!

    Myślę, że są dwa główne powody tego stanu rzeczy.

    Po pierwsze, w porównaniu do tradycyjnych rozwiązań jak C# czy Java, szybkość tworzenia oprogramowania w nim jest niesamowita. Olbrzymia ilosć pakietów pozwala na pobranie i zintegrowanie całych gotowych funkcjonalności jedną komendą npm i kilkoma linijkami kodu js. Co jest dla wielu ważne – znakomita większość na otwartych licencjach np. MIT.

    Ucząc się wszystkiego od zera (włącznie z js;), w krótkim czasie, udało mi się wraz z kolegą zrobić stronę dla znajomych graczy RPG. Wystarczyło poskładać kilka gotowych komponentów (do chatu, do video konferencji, komunikacji z bazą danych czy wysyłania maili) – więcej zajęło zrobienie grafiki i kontentu niż samego silnika. Po tych doświadczeniach coś w koło 100 godzin pracy zajęło nam uruchomienie pierwszego start-upu (efekt można zobaczyć tutaj: http://www.cometcall.com).

    Po drugie – jeden język programowania po stronie serwera i klienta sprawia, że nie trzeba się przestawiać z jednego języka na inny realizując konkretną funkcjonalność. Co więcej można też, używać kodu wielokrotnie i wygodnie przesyłać zserializowane do JSON obiekty pomiędzy klientem a serwerem. Do kompletu dobrać bazę MongoDB i operować na niej właśnie javascriptem.

    Teraz czytałam o kilku świeżych technologiach pozwalających na tworzenie aplikacji natywnych również w tym języku.

    Kierunek rozwoju technologii związanych z językiem javascipt bardzo mi się podoba – jeden język niezależnie od technologii. Choć muszę przyznać, że przestawiając się z C# bardzo dotkliwie odczułam brak silnego typowania;)

  2. Nie rozumiem zachwytów nad node i ilością pakietów. Przecież te pakiety to drobnica (osobny do ansi bell, osobny do czegos innego), zobaczcie ile syfu sciaga npm – 50MB i kilka tysięcy plikow, żeby wystartować gulpa. Do tego ciagle niezgodności, trzeba robic rebuild. Porzucane projekty, beznadziejna dokumentacja. Organizacja modułów woła o pomstę do nieba.

    Dodajmy jezyk javascript, który nie nadaje sie do dużych projektów. Jakby był super jezykiem, dawno temu wyszedłby z przeglądarek.

    Co z tego, ze można zrobić serwer www z 3 linijek – normalne projekty na tym nie polegają.

    Event driven? Przeciez to jest stosowane WSZEDZIE, czy winforms, czy www, ASPnet, etc, przecież nikt nie programuje przez polling.

    Porownajcie sobie to z zapisem w Ruby. Żeby nie było – nie jestem programista ruby.

     

    Prosta zasada – jak cos jest do wszystkiego, jest do niczego.

    1. Dzięki za komentarz.

      Ten post napisałem w 2011 roku, kiedy jeszcze nie do końca było wiadomo co wyjdzie z node. Była to wtedy ciekawa ciekawostka i taka była idea pisania tych artykułów wtedy – o ciekawostkach. Przyznam, że od wtedy nie używałem realnie node.js w żadnym projekcie. Nie pisałem też za dużo kodu w JS. Nie mniej jednak…

      Minęło kilka lat i czy się to nam podoba czy nie, node jest zdecydowanie mainstremową technologią wspieraną przez większość (wszystkich?) dużych vendorów i śmiem twierdzić, że na dzisiaj ma zdecydowanie szersze i bogatsze wsparcie w postaci oferty hostingowej, narzędziowej i wszelakiej … niż wspomniane Ruby.

      Nie jestem wielkim fanem JavaScript jako języka. Nie zmienia to jednak faktu, że dzisiaj jest to jeden z ważniejszych języków programowania w ogóle. Między innymi dzięki bardzo dużym inwestycjom runtime’y JS są mega wydajne. Próg wejścia dla programistów jest relatywnie niewielki. Narzędzi wspierających jest bardzo dużo – zastosowania szerokie.

      Wbrew temu co piszesz, JavaScript już dawno wyszedł z przeglądarki. Dziś jest używany do pisania aplikacji desktop (edytor Atom albo Visual Studio Code), aplikacji mobilnych (tak, tak… wiem, że facebook przeszedł z JS na natywne – nie mniej jednak dużo biznesowych, mniejszych aplikacji jest tak pisana), aplikacji server-side (poza wspomnianym node, chociażby część baz NoSQL zawiera w sobie silnik JS jako język do operowania danymi) i wiele innych. Windows w nieudanej wersji 8 i być może bardziej udanej 10 (nie używałem) mocno stawia na aplikacje pisane w JS (między innymi oczywiści). Są (dość skuteczne) narzędzia do kompilacji innych popularnych języków do JS (np. emscripten) oraz języki celujące w JS jako runtime (TypeScript na przykład).

      Nawiązując do zarzutu, że w „prawdziwych projektach” nie liczy się, że serwer www stawia się w 3 liniach – trzeba wyraźnie zdefiniować co to są te projekty. Zakładam, że przez prawdziwe rozumiesz te, które sam realizujesz i tam zastosowanie node.js nie jest uzasadnione. Nie mam jak dyskutować – co więcej, być może jest to prawda. Jednak dzisiaj gdy bardzo istotne stało się pojęcie micro-service architecture, w prawdziwych i dużych systemach, spotyka się aplikacje kilkadziesiąt / kilkaset linijkowe, które startują swój mały serwer www i realizują jedną konkretną, być może business critical, usługę. Moim zdaniem to są „prawdziwe projekty” i node.js (jak i wiele innych technologii) się tam nadaje bardzo dobrze.

      Podsumowując, nie zgadzam się z Tobą :)

      No i ostatecznie – ani JS ani node nie jest do wszystkiego. Ale podobnie jak Java, C#/.NET, Ruby, PHP, Python, C++, Scala i wiele innych jest to środowisko programistyczne ogólnego przeznaczenia do tworzenia małych, średnich i dużych aplikacji różnego typu.

  3. Matt Mullenweg współtwórca WordPress zadał społeczności skupionej wokół tego projektu, pracę domową do odrobienia : Learn JavaScript, Deeply.
    Być może JS wyprze PHP, może to się dokonać przy zatwierdzonej specyfikacji ES7.

    1. Z dwojga złego nie wiadomo co wybrać – PHP vs. JS :) Nie mniej biorąc pod uwagę wydany niedawno PHP7, którego changelog zaczyna się od:

      • Improved performance: PHP 7 is up to twice as fast as PHP 5.6
      • Significantly reduced memory usage

      … wydaje mi się, że koniec PHP wcale nie jest blisko nas.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.