[[ Tari Balázs / 2019-05-31]]
// Node //
531
FS, JS könyvtárak és Node.js modulok, NPM, nodemon

Modulok

A JavaScript (mint nyelv) már hosszú ideje támogatja a modulokat. Rendkívül sok előny származik a modulok használatából, melyek közül leginkább kiemelendőek az alábbiak: karbantarthatóság, névtér, újrafelhasználhatóság. A modulok célja az, hogy az egyes különálló futattható fájlokban ne kelljen ugyanazon kívánt funkciók eléréséhez újra deklarálni ugyanazt az utasítás sorozatot, hanem megegyezés szerint egy fájlban deklaráljuk az adott funkciót és mégis hozzáférhetőek legyenek más fájlok számára pusztán a megfelelő kulcsszavak használatával. Annak ellenére, hogy a JavaScript az ES5 idején (és előtte) nem rendelkezett beépített modulokkal, az idő előrehaladtával a nyelvet használó és fejlesztő közösség által jelentősen letisztult a teljes modulrendszer használata, melyet megörökölt az ES6:

  • Minden egyes modul egy külön fájlban elhelyezett kódrészlet, mely végrehajtódik amint betöltődik.

  • Ezen kódrészlet tartalmazhat változó és függvény deklarációkat. Alapértelmezetten ezek a modulon belül lokális hatókörrel rendelkeznek, azaz az egységbezárás koncepcióját valósítják meg.

  • Ezeket a modulokat lehet exportálni és importálni. Az előbbiből következik az a dolog, hogy egy modul több másik modult is importálhat a modulok hivatkozásával, mely történhet útvonalak megadásával (relatív vagy abszolút) vagy a nevén nevezve. A hivatkozást követően történik a modul példányosítása, mely azinkron módon történik.

  • A modulok singleton-ok. Akárhányszor betölthetünk egy modult, ugyanúgy egyetlen példánya fog létezni.

A koncepció megértéséhez vizsgáljuk meg a lenti példát! Definiálva van egy Felhasznalo osztály az innenexportalunk.js fájlban, nev és eletkor tulajdonságokkal Ezen felül a nevkiir és az eletkorkiir függvények. A célunk az, hogy exportáljuk a felhasznalo osztályt az innenimportalunk.js fájlba. Ezt kétféleképpen tehetjük meg: export default vagy export. Szintaxisa szerint az első megvalósítási lehetőség úgy néz ki, hogy használjuk a felhasznalo osztály deklarációja elé az export default kulcsszót (alapértelmezetten csak egy dolgot lehet exportálni egy fájlból, legyen ez az osztály), a függvények deklarációja elé pedig az export kulcsszót. Egy másik megközelítése a dolgok exportálásánal a module.exports kulcsszó használatán alapszik. Objektumot deklaráljunk literálként uzenet névvel, hozzunk létre neki tulajdonságot szoveg névvel és adjuk át neki a "Az exportálás sikeresen megtörtént!" stringet. Ezt az objektumot úgy exportálhatjuk, hogy értékül adjuk a module.exports-nak. Az innenimportalunk.js fájlban úgy tehetjük elérhetővé az előzőleg alapértelmezetten kiexportált osztályt, hogy az import kulcsszó után írjuk az osztály elnevezését (Felhasznalo), azt követően a from kulcsszót és végül az importálás (relatív) útvonalát ''-be foglalva. Végezetül lepéldányosítjuk az osztályt (mint mint felhasznalo nevezetű objektum) Péter névvel és 19 életkorral. Az exportált és importált osztálynévnek nem kell feltétlenül megegyeznie, viszont egy fájlon belül konvenció szerint azonos legyen az importálási név. Ez vonatkozik a példányosításra is. A nem alapértelmezetten exportált dolgok importálásához -ba foglalva meghívhatjuk őket a nevüket beleírva. Ha más néven szeretnénk meghívni, mellé írjuk az as alias kulcsszavakat, ahol az alias a tetszés szerinti elnevezés. A module.exports-szerint exportált objektumot a require() kulcsszó használatával tehetjük meg. Az argumentumába írjuk a fájl relatív útvonalát '' közé végül az importált értéket (mint objektum) az eztkapjuk nevű változóba.

// innenexportalunk.js
 
export default class Felhasznalo {
constructor(nev, eletkor){
this.nev = nev;
this.eletkor = ev;
}
};
 
export const nevkiir(felhasznalo) => {
console.log(`A felhasználó neve: ${felhasznalo.nev}`);
};
 
export const eletkorkiir(felhasznalo) => {
console.log(`A felhasználó életkora: ${felhasznalo.eletkor}`);
};
 
let uzenet = {};
 
uzenet.szoveg = "Az exportálás sikeresen megtörtént!";
 
module.exports = uzenet;
 
// innenimportalunk.js
 
import Felhasznalo, {nevkiir, eletkorkiir} from './innenexportalunk.js';
 
const eztkapjuk = require('./innenexportalunk.js');
 
const uzenetkiir() => {
console.log(eztkapjuk.uzenet);
};
 
uzenetkiir();
// Az exportálás sikeresen megtörtént!
 
const felhasznalo = new Felhasznalo('Péter', 19);
 
console.log(felhasznalo);
nevkiir(felhasznalo);
// A felhasználó neve: Péter
eletkorkiir(felhasznalo);
// A felhasználó életkora: 19

NPM

Az NPM a Node Package Manager szavak rövidítése, ami elsősorban egy online platformot takar (https://npmjs.com), másrészt egy parancssoron elérhető szolgáltatást. Az elsőt arra lehet használni, hogy JavaScript nyelven írt (a CommonJS specifikációit követve) modulodat megoszthasd teljesen ingyen másokkal. A kereső feltületén keresztül a megfelelő kulcsszavakat megadva kidob egy a keresés feltételeinek megfelelő találati listát azokból a könyvtárakból, amiket mások, vagy te magad már feltöltöttél. Mivel JavaScriptben íródtak, nagy a valószínűsége, hogy mind szerveren, a parancssoron, vagy akár a böngészőn le tudnak futni. A feltelepített modulokat a require('modulnev') paranccsal tudjuk elérni. Ezzel a paranccsal egy objektumot kapunk vissza, melyet egy tetszés szerinti változóhoz rendelhetünk. Az NPM parancssori változata egyfajta kiegészítője az online grafikus felületnek. Telepítésének előfeltétele a NodeJs (valamelyik verziója). Magát a telepítést az npm install npm paranccsal tehető meg. Többek között arra használják, hogy telepíthessünk vagy törölhessünk modulokat. A telepítés során megszabhatjuk, hogy melyik verziót szeretnénk telepíteni, ha el szeretnénk kerülni a későbbiekben az inkompatibilitást. A telepített modulok neveit és verziójukat nyilván tarthatjuk az úgynevezett package.json fájlban, amit mi magunk is létrehozhatunk, vagy egy template projekt közben automatikusan legenerálódik. Az npm install paranccsal a package.JSON által nyilván tartott összes modul feltelepül a node_modules könyvtárban. Egy modul gyakran sok más modul előfeltétele is lehet. Emiatt viszont nem kell aggódni, az NPM elvégzi a számunkra a piszkos munkát azzal, hogy megkeresi és telepíti az összes szükséges modult.

Nodemon

Amikor az éppen futó kódunkon végzünk el változtatásokat, a mentést követően nem lépnek érvénybe ezen változtatások. Minden egyes alkalommal újra kell indítani a teljes programot. Komplexebb applikációk esetén már egy csomó időt elvesz a fejlesztőktől. A probléma megoldására alkották meg a Nodemon modult. Visszatérve a projekt_neve mappához, egészítsük ki a fejlesztői környezetünket a modul feltelepítésével az npm install -g nodemon paranccsal. A telepítés ezúttal globális lesz ami azt jelenti, hogy minden egyes projektnél elérhető lesz ez a funkció akár telepítve volt előtte lokálisan, akár nem. A telepítés után indítsuk újra a szervert ezúttal a nodemon server.js paranccsal. Eszközöljünk rajta némi változtatést a szerveren, mentsük el és nézzük meg mi történik!

> package name: (projekt_neve)
> entry point: (index) server.js
> version: (1.0.0)
> description:
> git reposatory:
> keywords
> author:
> license: (ISC)
> Is it OK (yes)

FS

A FileSystem, röviden FS a NodeJs olyan beépített modulja, melynek segítségével különböző fájlműveletek hajthatóak végre. A modul minden egyes metódusának deklarálva van a szinkron és aszinkron változata. Az aszinkron változat egy függvény paraméterrel többet vár, aminek van a hiba és a teljesített ága. Az aszinkron verzió implementálást gyakrabban használják, ugyanis addig nem tartóztatja fel a többi utasítás lefutását (non-blocking), szemben a szinkron verzióval. A két leggyakrabban használt fájlművelet az írás (write) és olvasás (read). A fájl beolvasásnál opcionálisan beállíthatjuk a karakter kódolást. A magyar ékezetek értelmezéséhez utf8-at állítsunk be. A két fájlművelet használalát bemutatjuk példákon keresztül, mind szinkron, mind aszinkron formájában.

Ezt a szöveget kell beolvasni!
var fs = require('fs');
 
// fájlból olvasás szinkron megvalósítása
 
var beolvasott_szoveg = fs.readFileSync('szoveg.txt','utf8');
console.log(beolvasott szoveg);
// Ezt a szöveget kell beolvasni.
 
// fájlba írás szinkron megvalósítása
 
fs.writeFileSync("masikszoveg.txt", "Ezt a másik szoveget kell másik fájlba kiírni!");
 
// fájlból olvasás aszinkron megvalósítás
 
fs.readFile('szoveg.txt', ,'utf8', (error, data) => {
if (error){
console.log(error);
} else {
console.log(data);
 // Ezt a szöveget kell beolvasni.
}
});
 
// fájlba írás aszinkron megvalósítás
 
fs.writeFile('masikszoveg.txt', "Ezt a másik szoveget kell másik fájlba kiírni!",
(error) => {
if (err){
console.log(error);
} else {
console.log("A fájlba írás sikeresen megtörtént");
}
});
on this page
back to top