\section{Node.js Alapok} \begin{frame}{Mi a Node.js?} \footnotesize A Javascript eredetileg kizárólag böngészőkben futott. A \textbf{Node.js} ezt változtatta meg: kiszedte a Google Chrome V8 motorját a böngészőből, és lehetővé tette, hogy Javascript kód a szerveren, önállóan is fusson -- így írhatunk vele backend alkalmazásokat, parancssori eszközöket, akár build-rendszereket is. \begin{itemize} \item JavaScript futtatókörnyezet a V8 motoron alapulva \item Szerveroldali JavaScript fejlesztés lehetősége \item Eseményvezérelt, nem blokkoló (non-blocking) I/O modell \item Létrehozta: Ryan Dahl (2009) \end{itemize} \begin{block}{Miért Node.js?} Ugyanazt a nyelvet használhatjuk frontend és backend oldalon is, hatalmas npm ökoszisztéma áll rendelkezésre szinte bármilyen problémára, és gyors vele a fejlesztés, prototípuskészítés. \end{block} \end{frame} \begin{frame}{Node.js architektúra} \footnotesize A Node.js két fő komponensre épül: a Javascript kódot lefordító és futtató \textbf{V8 motorra}, valamint a háttérben futó \textbf{libuv} könyvtárra, ami az aszinkron I/O műveleteket (fájl, hálózat) kezeli. \begin{columns} \begin{column}{0.48\textwidth} \begin{block}{V8 JavaScript Engine} \begin{itemize} \item Google Chrome motorja \item JIT (Just-In-Time) fordítás \item C++ nyelven íródott, rendkívül gyors \end{itemize} \end{block} \end{column} \begin{column}{0.48\textwidth} \begin{block}{libuv} \begin{itemize} \item Event loop implementáció \item Aszinkron I/O műveletek \item Cross-platform támogatás \end{itemize} \end{block} \end{column} \end{columns} \begin{alertblock}{Event Loop} Timers $\to$ Pending callbacks $\to$ Poll (I/O) $\to$ Check $\to$ Close callbacks. A Node.js egyetlen szálon (single-threaded) fut, de az I/O műveletek aszinkron módon, a háttérben zajlanak -- így egy lassú fájlművelet nem blokkolja a többi kérés kiszolgálását. \end{alertblock} \end{frame} \begin{frame}[fragile]{Első Node.js program} \footnotesize Nézzünk egy egyszerű, de tanulságos első programot, ami megmutatja, milyen beépített, Node.js-specifikus változókhoz férünk hozzá. \begin{block}{hello.js -- futtatás: \texttt{node hello.js}} \begin{lstlisting}[language=JavaScript,style=NodeJS] console.log('Hello, Node.js!'); console.log('Node verzio:', process.version); console.log('Aktualis konyvtar:', __dirname); \end{lstlisting} \end{block} \begin{alertblock}{Fontos} A Node.js nem böngésző! Nincs \texttt{window}, nincs \texttt{document}, de van helyette \texttt{global} (a böngésző \texttt{window}-jának megfelelője) és \texttt{process} (a futó Node.js folyamatról ad információt). \end{alertblock} \end{frame} \begin{frame}[fragile]{Modulrendszer -- CommonJS} \footnotesize Ahogy a kódunk növekszik, elkerülhetetlen, hogy több fájlra bontsuk. A Node.js hagyományos, alapértelmezett modulrendszere a \textbf{CommonJS}, ahol a \texttt{require} és a \texttt{module.exports} párossal osztunk meg kódot fájlok között. \begin{columns} \begin{column}{0.48\textwidth} \begin{block}{math.js -- export} \begin{lstlisting}[language=JavaScript,style=NodeJS] function add(a, b) { return a + b; } module.exports = { add }; \end{lstlisting} \end{block} \end{column} \begin{column}{0.48\textwidth} \begin{block}{app.js -- import} \begin{lstlisting}[language=JavaScript,style=NodeJS] const math = require('./math'); console.log(math.add(2, 3)); // 5 \end{lstlisting} \end{block} \end{column} \end{columns} \begin{block}{Beépített (core) modulok} A Node.js számos hasznos modult ad eleve a kezünkbe, telepítés nélkül: \texttt{fs} (file system, fájlkezelés), \texttt{path} (útvonalak kezelése), \texttt{http} (webszerver készítése). \end{block} \end{frame} \begin{frame}[fragile]{ES Modules (ESM)} \footnotesize A modern Javascript szabvány, az ECMAScript saját, egységes modulrendszert vezetett be \texttt{import}/\texttt{export} kulcsszavakkal -- ugyanezt ismerheted a frontend keretrendszerekből (React, Vue) is. A Node.js is támogatja ezt, ha bekapcsoljuk. \begin{columns} \begin{column}{0.48\textwidth} \begin{block}{math.mjs -- export} \begin{lstlisting}[language=JavaScript,style=NodeJS] export function add(a, b) { return a + b; } \end{lstlisting} \end{block} \end{column} \begin{column}{0.48\textwidth} \begin{block}{app.mjs -- import} \begin{lstlisting}[language=JavaScript,style=NodeJS] import { add } from './math.mjs'; console.log(add(2, 3)); \end{lstlisting} \end{block} \end{column} \end{columns} \begin{alertblock}{package.json} Az ESM használatához be kell állítani: \texttt{\{"type": "module"\}} a \texttt{package.json} fájlban -- ekkor a \texttt{.js} kiterjesztésű fájlok is ES modulként fognak viselkedni. \end{alertblock} \end{frame} \begin{frame}[fragile]{File System műveletek} \footnotesize A backend fejlesztés egyik leggyakoribb feladata fájlokkal dolgozni (konfiguráció olvasása, log írása, feltöltött fájlok kezelése). A Node.js \texttt{fs} modulja ehhez háromféle API-t is kínál. \begin{block}{Fájl olvasás -- Promise API (ajánlott)} \begin{lstlisting}[language=JavaScript,style=NodeJS] const fs = require('fs').promises; async function readData() { const data = await fs.readFile('input.txt', 'utf8'); console.log(data); } \end{lstlisting} \end{block} \begin{itemize} \item \texttt{readFileSync} -- szinkron, blokkolja a végrehajtást, amíg be nem fejeződik (kerülendő szerveroldalon) \item \texttt{readFile} callback-kel -- aszinkron, a régebbi, callback-alapú stílus \item \texttt{fs.promises} -- aszinkron, \texttt{async/await}-tel szépen, szinkron kódként olvasható -- ma ez az ajánlott megoldás \end{itemize} \end{frame} \begin{frame}[fragile]{HTTP szerver létrehozása} \footnotesize Ahogy korábban láttuk, a HTTP request-response modellt bármilyen nyelven meg lehet valósítani. Node.js-ben a beépített \texttt{http} modullal mindössze néhány sorból már működő webszervert tudunk indítani -- ez az alapja mindannak, amit a következő heteken Express.js-szel fogunk csinálni. \begin{block}{Egyszerű HTTP szerver} \begin{lstlisting}[language=JavaScript,style=NodeJS] const http = require('http'); const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello, Node.js szerver!\n'); }); server.listen(3000, () => { console.log('Szerver fut: http://localhost:3000'); }); \end{lstlisting} \end{block} \end{frame} \begin{frame}{Node.js vs. Böngésző} \footnotesize Fontos tudatosítani, hogy bár mindkét környezetben Javascript kód fut, a Node.js és a böngésző \emph{teljesen más} környezetet biztosítanak -- más API-k érhetők el, és más a rendeltetésük is. \begin{tabular}{|l|l|l|} \hline \textbf{Jellemző} & \textbf{Node.js} & \textbf{Böngésző} \\ \hline DOM API & Nincs & Van \\ \texttt{window} objektum & Nincs & Van \\ Globális objektum & \texttt{global} & \texttt{window} \\ File system & Van (\texttt{fs}) & Nincs \\ HTTP szerver & Készíthető & Nem \\ Használat & Backend, CLI & Frontend \\ \hline \end{tabular} \end{frame} \begin{frame}{Összefoglalás -- Node.js} \footnotesize \begin{block}{Node.js alapok} \begin{itemize} \item V8 engine alapú JavaScript futtatókörnyezet, szerveroldalon \item Event-driven, non-blocking I/O modell -- egy szálon, de aszinkron módon \item Modulrendszer: CommonJS (\texttt{require}) és ES Modules (\texttt{import}) \item Beépített modulok: \texttt{fs} (fájlok), \texttt{path} (útvonalak), \texttt{http} (szerver) \item HTTP szerver készítése pár sorban -- ez az alapja a jövő heti Express.js-nek \end{itemize} \end{block} \end{frame}