\section{NPM Package Manager} \begin{frame}[fragile]{Mi az npm?} \footnotesize Amint elkezdünk egy valós projekten dolgozni, hamar szükségünk lesz mások által megírt kódra -- ne írjunk újra mindent nulláról! Az \textbf{npm} (Node Package Manager) ebben segít: ez a Node.js hivatalos csomagkezelője, amivel telepíthetünk, frissíthetünk és megoszthatunk kódcsomagokat. \begin{itemize} \item Node Package Manager -- Node.js csomagkezelője \item A világ legnagyobb szoftver registry-je (2+ millió csomag) \item Node.js-szel együtt települ, külön telepíteni nem kell \item Projekt függőségek kezelése, verziószám ellenőrzése \end{itemize} \begin{block}{Verziószám ellenőrzése} \begin{verbatim} node --version npm --version \end{verbatim} \end{block} \end{frame} \begin{frame}[fragile]{npm alternatívái} \footnotesize Bár a tárgy során mindvégig az npm-et fogjuk használni, érdemes tudni, hogy nem ez az egyetlen csomagkezelő a Node.js ökoszisztémában -- a szakmában több helyen találkozhatsz az alternatíváival is. \begin{alertblock}{Alternatívák} \texttt{yarn} és \texttt{pnpm} -- ugyanazt a célt szolgálják, mint az npm, csak némileg gyorsabbak és hatékonyabbak lehetnek nagyobb projekteknél. A \texttt{pnpm} például egyetlen, megosztott tárolóban tartja a csomagokat, így lemezterületet spórol. \end{alertblock} A parancsok szinte megegyeznek egymással (\texttt{npm install} $\leftrightarrow$ \texttt{yarn add} $\leftrightarrow$ \texttt{pnpm add}), így ha megtanulod az egyiket, a többit is könnyen felveszed majd. \end{frame} \begin{frame}[fragile]{npm init -- Projekt inicializálás} \footnotesize Minden Node.js projekt egy \texttt{package.json} fájllal kezdődik, ami leírja a projekt metaadatait (nevét, verzióját, függőségeit). Ezt a fájlt az \texttt{npm init} parancs generálja le nekünk. \begin{block}{Interaktív projekt létrehozás} \begin{verbatim} npm init \end{verbatim} Ekkor az npm sorra megkérdezi a projekt nevét, verzióját, leírását, stb. \end{block} \begin{block}{Gyors inicializálás alapértelmezett értékekkel} \begin{verbatim} npm init -y \end{verbatim} \end{block} \end{frame} \begin{frame}{npm init -- mit hoz létre?} \footnotesize Mindkét változat ugyanazt az egy fájlt hozza létre -- csak abban különböznek, hogy megkérdezik-e tőlünk előtte a projekt adatait, vagy rögtön alapértelmezett értékekkel dolgoznak. \begin{alertblock}{Eredmény} Létrejön a \texttt{package.json} fájl, amely a projekt metaadatait tartalmazza, és ami a projektünk "személyi igazolványaként" működik: ebben tároljuk a nevét, verzióját, a függőségeit és a saját parancsainkat is. \end{alertblock} Ha egy projektet klónozol githubról, az első dolgod mindig az legyen, hogy megnézed a \texttt{package.json}-t -- ebből azonnal kiderül, milyen technológiákat használ, és hogyan indítható. \end{frame} \begin{frame}[fragile]{package.json struktúra} \footnotesize Érdemes megismerkedni a \texttt{package.json} legfontosabb mezőivel, hiszen ez a fájl fogja a félév során minden projektünket összefogni. \begin{lstlisting}[language=JavaScript,style=NodeJS] { "name": "backend-app", "version": "1.0.0", "main": "index.js", "scripts": { "start": "node index.js", "dev": "nodemon index.js" }, "dependencies": { "express": "^4.18.2" }, "devDependencies": { "nodemon": "^3.0.1" } } \end{lstlisting} \end{frame} \begin{frame}{package.json mezői} \footnotesize A \texttt{scripts} mező alatt saját parancsainkat definiálhatjuk, a \texttt{dependencies} és \texttt{devDependencies} pedig a projekt függőségeit sorolja fel. \begin{itemize} \item \texttt{name}, \texttt{version} -- a projekt azonosítója és verziója \item \texttt{main} -- melyik fájl a belépési pont, ha valaki \texttt{require}-olja a projektünket \item \texttt{scripts} -- rövid parancsok gyakori feladatokra (erről bővebben pár dia múlva) \item \texttt{dependencies} / \texttt{devDependencies} -- a projekt függőségei (erről is bővebben mindjárt) \end{itemize} \end{frame} \begin{frame}[fragile]{Csomagok telepítése -- production függőségek} \footnotesize Amikor egy csomagra van szükségünk, az \texttt{npm install} (röviden \texttt{npm i}) paranccsal tudjuk hozzáadni a projekthez. Fontos eldönteni, hogy a csomagra csak fejlesztés közben, vagy éles működéskor is szükség lesz-e. \begin{block}{Production függőségként} \begin{verbatim} npm install express npm i express \end{verbatim} \end{block} Ezek a csomagok a \texttt{dependencies} alá kerülnek a \texttt{package.json}-ben -- ezek nélkül az alkalmazásunk éles környezetben sem tudna elindulni, hiszen a kódunk ténylegesen használja őket futás közben (pl. az Express.js keretrendszert magát). \end{frame} \begin{frame}[fragile]{Csomagok telepítése -- development függőségek} \footnotesize Vannak olyan eszközök, amikre csak a fejlesztés közben van szükségünk (pl. automatikus újraindítás, tesztelés, kódformázás) -- ezeket nem érdemes az éles szerverre is felmásolni. \begin{block}{Development függőségként} \begin{verbatim} npm install --save-dev nodemon npm i -D nodemon jest eslint \end{verbatim} \end{block} \begin{alertblock}{Mi a különbség?} \texttt{dependencies}: éles környezetben is kell \quad|\quad \texttt{devDependencies}: csak fejlesztéshez (pl. tesztelő, formázó eszközök) \end{alertblock} \end{frame} \begin{frame}{Semantic Versioning (SemVer)} \footnotesize Az npm csomagok verziószámozása egy szigorú, háromrészes konvenciót követ, amiből azonnal leolvasható, hogy egy frissítés mekkora változást hozhat. \begin{block}{Verzió formátum} \texttt{1.2.3} $\to$ \texttt{1} (major) . \texttt{2} (minor) . \texttt{3} (patch) \end{block} \begin{itemize} \item \textbf{MAJOR:} nem kompatibilis, "törő" API változás \item \textbf{MINOR:} új funkció, de visszafelé kompatibilis \item \textbf{PATCH:} hibajavítás, visszafelé kompatibilis \end{itemize} \end{frame} \begin{frame}{SemVer jelölések a package.json-ban} \footnotesize A \texttt{package.json}-ban a verziószám elé írt jel (\texttt{\^{}} vagy \texttt{\textasciitilde}) szabja meg, hogy \texttt{npm install}/\texttt{npm update} során milyen új verziókat fogadunk el automatikusan. \begin{tabular}{|l|l|} \hline \textbf{Jelölés} & \textbf{Jelentés} \\ \hline \texttt{1.2.3} & Pontosan 1.2.3 verzió \\ \texttt{\^{}1.2.3} & $\geq$ 1.2.3 és $<$ 2.0.0 (MINOR frissítések engedélyezve) \\ \texttt{\textasciitilde 1.2.3} & $\geq$ 1.2.3 és $<$ 1.3.0 (csak PATCH frissítések) \\ \texttt{latest} & Mindig a legfrissebb verzió \\ \hline \end{tabular} \begin{alertblock}{Gyakori alapértelmezés} Az \texttt{npm install csomagnev} alapból a \texttt{\^{}} jelölést használja -- ez a leggyakoribb, kényelmes középút a stabilitás és a frissesség között. \end{alertblock} \end{frame} \begin{frame}[fragile]{npm scripts} \footnotesize A \texttt{package.json} \texttt{scripts} mezőjében saját, rövid parancsokat definiálhatunk a gyakran ismételt feladatokra (indítás, tesztelés, linting) -- így nem kell mindig hosszú parancsokat begépelni. \begin{lstlisting}[language=JavaScript,style=NodeJS] { "scripts": { "start": "node index.js", "dev": "nodemon index.js", "test": "jest", "lint": "eslint ." } } \end{lstlisting} \begin{block}{Scripts futtatása} \begin{verbatim} npm run dev npm start # 'run' nelkul is mukodik \end{verbatim} \end{block} \end{frame} \begin{frame}{node\_modules és package-lock.json} \footnotesize Amikor telepítünk egy csomagot, az npm két dolgot hoz létre: egy \texttt{node\_modules} mappát a tényleges kóddal, és egy \texttt{package-lock.json} fájlt. Fontos tudni, melyiket kell git-ben verziókövetni, és melyiket nem. \begin{columns} \begin{column}{0.48\textwidth} \begin{block}{node\_modules} \begin{itemize} \item A telepített csomagok tényleges kódját tartalmazó mappa \item Nagyon nagy tud lenni (akár több száz MB) \item Ne commitoljuk git-be! \item Újragenerálás: \texttt{npm install} \end{itemize} \end{block} \end{column} \begin{column}{0.48\textwidth} \begin{block}{package-lock.json} \begin{itemize} \item Pontosan rögzíti, melyik csomagból melyik verzió lett telepítve \item Determinisztikus, mindenkinél ugyanazt eredményező telepítést biztosít \item Ezt viszont commitoljuk git-be! \end{itemize} \end{block} \end{column} \end{columns} \end{frame} \begin{frame}[fragile]{Hasznos npm parancsok és npx} \footnotesize Néhány további parancs, amire a mindennapi munka során gyakran szükség lesz: a projekt állapotának ellenőrzésére, illetve arra, hogy egy csomagot telepítés nélkül, egyszer futtassunk le. \begin{columns} \begin{column}{0.48\textwidth} \begin{block}{Karbantartás} \begin{verbatim} npm list npm outdated npm audit npm audit fix \end{verbatim} \end{block} \end{column} \begin{column}{0.48\textwidth} \begin{block}{npx -- futtatás telepítés nélkül} \begin{verbatim} npx prisma init npx tsx index.ts \end{verbatim} \end{block} \end{column} \end{columns} Az \texttt{npx} egy segédeszközt csak egyszer, ideiglenesen tölt le és futtat le, anélkül, hogy állandó jelleggel telepítené a gépünkre. \end{frame} \begin{frame}{Összefoglalás -- NPM} \footnotesize \begin{block}{npm alapok} \begin{itemize} \item npm: Node Package Manager, 2+ millió elérhető csomag \item \texttt{npm init} -- projekt inicializálása, \texttt{package.json} létrehozása \item \texttt{npm install/uninstall/update} -- csomagkezelés \item \texttt{dependencies} vs \texttt{devDependencies} -- éles vs csak fejlesztői függőség \item Semantic Versioning: \texttt{MAJOR.MINOR.PATCH} \item \texttt{node\_modules} (ne commitold), \texttt{package-lock.json} (ezt viszont igen) \item \texttt{npx}: csomagok egyszeri futtatása telepítés nélkül \end{itemize} \end{block} \end{frame}