Dawid Panfil

Node.js – pierwsze starcie

Czasem… w życiu przychodzą takie chwile, że trzeba napisać troszkę backendu w JavaScript. Broniłem się rękoma i nogami, aby tego nie robić. Wyszło, że jednak nie potrzebnie, bo Node.js jest całkiem przyjemny.

Wrażenia z używania

Postawienie pierwszej aplikacji w node.js (w porównaniu do PHP) jest o wiele prostsze i szybsze. Nie potrzeba instalacji i konfiguracji nginx’a czy apache. Wystarczy dodać jakiś system szablonów i mongoDB w którym nie tracimy czasu na tworzenie schematu tabel i mamy gotowe środowisko developerskie.

Moim zdaniem node.js nada się do szybkiego postawienia aplikacji – makiety, która jeśli się przyjmie można przepisać na coś lepszego – lub do mikro serwisów (czy po angielsku jak ktoś woli: Microservices). Ja na potrzeby tego kursu/wpisu wybiorę opcję numer jeden i zrobimy jakiś prosty serwis.

Jednak, żeby nie było aż tak prosto zrobimy sobie serwis rezerwacji miejsc u kosmetyczki na wybrane usługi. Zrobimy podstawową stronę, która będzie zawierała:

  • stronę główną – strona statyczna zachęcająca się do zapoznania z ofertą
  • o nas – kolejna strona statyczna, z tym że posiadać będzie formularz kontaktowy i mapkę
  • nasze usługi – lista usług, którą można edytować z panelu administracyjnym. Wybranie konkretnej usługi pokaże formularz rezerwacyjny z możliwością wyboru daty i godziny.
  • kalendarz dla klientów– pokazuje wolne i zajęte terminy. Kliknięcie w wolny termin przekierowuje do listy usług, które można wykonać w danym dniu i godzinie.
  • panel administratora – zawiera tabelki rezerwacji wraz z statusem (opłacona, anulowana, wykonana), dajemy możliwość przeniesienia rezerwacji na inny dzień.

Jak widzisz pracy mało nie będzie, także sporo różnych wątków uda nam się tutaj poruszyć.

Instalacja środowiska

No to zacznijmy od początku. Trzeba zainstalować node oraz npm.

sudo apt-get update
sudo apt-get install nodejs npm

Sprawdźmy czy wszystko jest poprawnie:

npm -- version
3.5.2

node --version
v8.10.0

tak mniej więcej powinno to wyglądać. Teraz dwa słowa do wyjaśnienia.

Czym jest NPM?

NPM – domyślny manager pakietów dla środowiska Node.js, może być także używany do zarządzania warstwą front-end aplikacji WWW. Teraz po polsku. Npm to manager pakietów – czyli osobnych bibliotek wspomagających nasze programowanie. Instaluje i pilnuje on wszystkich zależności jakie wychodzą między bibliotekami. Naszym zadaniem jest jedynie wybranie odpowiednich pakietów i wpisanie ich do pliku package.json.

Przykładowego pliku nie będę teraz pokazywał, bo w kolejnej części wpisu będzie on się jeszcze pokazywać.

Czym jest node.js?

Jest to wieloplatformowe środowisko uruchomieniowe o otwartym kodzie do tworzenia aplikacji typu server-side napisanych w języku JavaScript. I znowu po polsku node umożliwia pisanie backendu w JS. Główną cechą node.js jest to, że jest asynchroniczny. Jest to zarazem fajna i utrudniająca życie cecha. Przykład oczywiście później pokażę.

Stajemy teraz przed najważniejszym pytaniem. Jak używać node.js? Jak najprościej. Stwórz plik app.js (lub inaczej go nazwij – jak wolisz i umieść w nim:

console.log('test');

i uruchom w konsoli:

node app.js

dostaniesz napis test. Składnia tego polecania jest następująca: node <nazwa_pliku>. No ale nie będziemy w ten sposób się bawić i pisać cały czas node <nazwa_pliku> od czegoś mamy npm.

Tworzenie struktury aplikacji

To zabieramy się do kodowania. Troszkę późno zaznaczam, ale jeśli chcesz czytać dalej to musisz chociaż w minimalnym stopniu znać JavaScript i uzupełniać ewentualne braki w między czasie. Oczywiście będę starał się wrzucać odpowiednie odnośniki, aby było Ci lżej.

Są dwa sposoby na rozpoczęcie nowego projektu. Jeśli lubisz pogadać z komputerem wpisz:

npm init

Jeśli jednak chcesz szybko i bezboleśnie:

npm init -y

Oba rozwiązania są poprawne. Którego użyjesz jest kwestią tego jak Ci wygodniej. Tylko przed tym zawsze przejdź do miejsca, gdzie mają być pliki projektu. Dostaniemy wtedy piękny plik package.json w folderze.

Wrote to /home/dawid/Projekty/hair-styling/package.json:

{
  "name": "hair-styling",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Dość zwięźle opisując: dostaliśmy plik, który opisuje naszą aplikację. Jak widzisz nazwałem ją hair-styling. W scripts wpisujemy sobie skróty tego, co npm ma odpalić. Z ciekawości możesz sobie wpisać w konsoli:

npm run test

I dostaniesz napis: Error: no test specified i długą informację o błędzie z statusem wyjścia 1, czym oczywiście się teraz nie przejmujemy. Aczkolwiek w ten sposób działają te skrypty.

npm run <nazwa skryptu/polecenia>

Instalacja podstawowych pakietów

Czyli zabieramy się za instalowanie paczek/modułów jakie potrzebujemy do stworzenia aplikacji. Od strony developerskiej potrzebujemy:

  • typescript – w skrócie typowany/obiektowy javascript. Oczywiście powiedziane troszkę na wyrost bez odpowiedniego szacunku dla TS 😉
  • tslint – program, który pomoże utrzymać kod w czystości i porządku dla języka Typescript
  • nodemon – taki mały programik, który ogranicza ilość przekleństw, gdy oczekujemy zmian, a ich nie widzimy. Nasłuchuje zmiany i automatycznie restartuje nasz serwer.

Ogólne paczki:

  • mongoose – moduł, który obsługuje bazę mongoDB
  • express.js – framework dla Node.js do tworzenia stronek opartych na protokole HTTP (czyli klasyczne strony internetowe)

Zabieramy się do instalacji. Dla paczek dev korzystamy z flagi -D natomiast zwykłych paczek po prostu dajemy –save:

npm install -D typescript tslint nodemon
npm install --save mongoose @types/mongoose express @types/express ts-node

Jak widzisz można instalować kilka modułów jednocześnie. Otwórz sobie plik package.json i zobacz, że doszły dwie kolejne gałęzie: devDependencies oraz dependencies. W nich natomiast masz te moduły/paczki o których wspominałem wyżej. Tymi @types/* się nie przejmuj póki co. Możesz sobie poszukać i poczytać w między czasie. Czym jest ts-node na ten moment też nie musisz się zastanawiać.

Konfiguracja

Niestety jeszcze to nie wszystko i do przyjemności pisania kodu dzieli nas kilka plików.

Najpierw zajmiemy się tslint. Czyli wpisujemy reguły sprawdzania naszych plików. Robimy to poleceniem:

node_modules/bin/tslint --init

Wygeneruje to nam plik tslint.json, który wygląda domyślnie w ten sposób:

{
    "defaultSeverity": "error",
    "extends": [
        "tslint:recommended"
    ],
    "jsRules": {},
    "rules": {},
    "rulesDirectory": []
}

Czyli wykorzystujemy domyślne reguły, które możemy dalej rozszerzyć nadpisując rules. Przykładowo wymaganie używania pojedynczych apostrofów:

  "quotemark": [true, "single"] 

Dopisz sobie to do rules, oraz w wolnej chwili doczytaj sobie jakie jeszcze można tam wrzucić reguły. My wraz z rozwojem aplikacji będziemy uzupełniać sobie reguły, tak aby było nam wygodniej – w końcu się uczymy więc nie musi być wszystko zgodnie z rekomendowanymi standardami i lekko będziemy naginać te reguły pod siebie 😉

W ten sam sposób generujemy sobie plik tsconfig.json, do czego służy – sama nazwa mówi.

 node_modules/.bin/tsc --init 

Wygeneruje to nam dość duży plik, który w większości jest w komentarzach, jednak nie potrzebujemy aż tak dużego pliku… w szczególności na tym etapie nauki. Także jak na dobrego programistę przystało posiłkujemy się naszą biblią – czyli stackoverflow:

{
  "compileOnSave": true,
  "compilerOptions": {
    "target": "es5",
    "allowSyntheticDefaultImports": true,     /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    "outDir": "./dist/",
    "baseUrl": "src",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2016",
      "dom"
    ]
  }
}

Ten wpis nie jest typowo o TypeScript, także nie będę starać się wyjaśniać co tutaj jest, może zrobię to w osobnym wpisie. Najważniejsze jest dla nas tutaj baseUrl i outDir. Pierwszy to katalog z naszymi plikami, a w drugim natomiast jest przetworzony TS do JS. Czyli stwórz sobie od razu folder src. Natomiast folder dist odpuść sobie, on sam się stworzy w swoim czasie.

Czas zacząć kodować w Node.js

Tak w końcu jesteśmy przy tym najważniejszym miejscu. Zaczynamy pisać kod. Niestety dzisiaj to tylko zwykła pokazówka, że coś się dzieje i coś widać.

Także w folderze src tworzymy sobie plik index.ts z następującą treścią:

import express from 'express';
const app = express();

// home
app.get('/', (request, response) => {
    response.send('Hello World!!');
});

app.listen(3000, () => console.log('Example app listening on port' + ':3000!'));

Tłumacząc na szybko: jak zauważyłeś wszędzie pojawiają się moduły. Framework express też jest takim modułem/biblioteką. Wszystko co używamy musimy zaimportować (czyli inaczej dodać) do pliku, aby node.js wiedział co użyć.

Następnie tworzymy sobie obiekt app z express (przypomnę, że to jest framework do tworzenia stron www i wszystko jest zależne od niego).

Kolejnym krokiem jest stworzenie sobie routingu – czyli ścieżek dostępu do naszej strony. Takich ścieżek może być wiele i kilka rodzajów (protokół HTTP), bo możemy wysyłać dane przez POST/PUT, usuwać je przez DELETE czy po prostu pobrać przez GET. Na ten moment skupmy się tylko na metodzie GET i jej strukturze:

 app.get('path', callback); 

Wyjaśnienie: path to ścieżka dostępu, callback to jest funkcja która ma zostać wykonana. Przyjmuje ona dwa parametry request i response.

Na koniec najważniejsze – nasłuchiwanie portu, czyli gdzie znaleźć naszą aplikację. W tym wypadku pod adresem: localhost:3000. Nie próbuj – jeszcze nie zadziała.

Skrypty w package.json

Pamiętasz ten plik jeszcze? Trzeba w końcu w nim pogrzebać. Dopiszemy sobie tylko do scripts linijkę:

"serve": "node  -r ts-node/register ./src/index.ts"

Oczywiście pamiętaj, o poprawnym zapisie – nie zapominaj o ewentualnych przecinkach. Teraz możesz uruchomić ten skrypt wpisując w konsoli:

npm run serve

Jeśli jest wszystko okej to zobaczysz następujący komunikat:

> hair-styling@1.0.0 serve /home/dawid/Projekty/hair-styling
> node  -r ts-node/register ./src/index.ts

Example app listening on port:3000!

I w tym momencie nie dotykaj konsoli, program ma być tak włączony. Za to uruchom przeglądarkę wpisując adres: localhost:3000. Powinien pojawić Ci się cudny napis:

Hello World!!

Jeśli nie to coś popsułeś i zapewne w konsoli dostaniesz informacje.

O ścieżkach w Node.js słów kilka

Kilka akapitów wyżej wspomniałem, że trzeba przygotować kilka stron, wszystkie będą opierały się na GET, także ja przedstawię kilka sposobów na tworzenie tych callbacków.

Pierwszy to osobna skrócona forma zapisu funkcji, którą wrzuciliśmy jako parametr callback dla strony głównej.

Drugi to zwykła funkcja, tak samo wrzucona w callback:

app.get('kontakt', function (request, response) {
    response.send('strona kontaktowa');
});

Można oczywiście wyciągnąć tą funkcję na zewnątrz:

app.get("/o-nas", aboutMe);

function aboutMe(request, response) {
    response.send('Jestem w stronie o mnie');
}

lub nawet do osobnego pliku, czy nawet klasy. Klasa taka nazywa się kontrolerem (ang controller), a wszystkie te ścieżki /, o-nas czy kontakt są routingiem, ale tym zajmiemy się już w następnym wpisie, bo za dużo informacji na raz też jest niedobre.

Jednak w wolnej chwili jeśli nie znasz czegoś takiego jak wzorzec MVC to zapoznaj się z tym terminem, będzie Ci łatwiej przetrawić informacje w następnym wpisie. Jeśli masz jakieś pytania bądź wątpliwości, zadaj je w komentarzu, odpowiem najszybciej jak potrafię! 🙂

Wszystko to co pokazałem, staram się pokazywać w najprostszy sposób – nie zawsze zgodny z ogólnymi praktykami. Także pamiętaj, aby uzupełniać wiedzę, którą Ci przekazuje w moich artykułach. Jeśli będziesz miał z czymś problem to zachęcam do komentowania.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *