avansat
Tehnologii Web
Dr. Sabin Buraga[Link]/~busaco
programare Web: [Link] – supliment
Prof. Sabin Corneliu Buraga – [Link]/~busaco/
Dr. Sabin Buraga[Link]/~busaco
„Cine a văzut vreodată o bijuterie frumos cizelată
de bijutier cu ajutorul ciocanului?”
Jan Amos Comenius
Dr. Sabin Buraga[Link]/~busaco
JavaScript (ECMAScript)
un limbaj de programare pentru Web
Inventat de Brendan Eich (1995)
Dr. Sabin Buraga[Link]/~busaco
detalii în cadrul prelegerilor
Limbajul de programare JavaScript.
Aspecte esențiale
[Link]/~busaco/teach/courses/staw/[Link]#week2
Limbajul de programare JavaScript.
Aspecte moderne: ES6 et al.
[Link]/~busaco/teach/courses/staw/[Link]#week3
a se considera și
Ingineria dezvoltării aplicaţiilor JavaScript
[Link]/~busaco/teach/courses/staw/[Link]#week7
Cum dezvoltăm cu JavaScript
aplicații Web la nivel de server?
Dr. Sabin Buraga[Link]/~busaco
[Link]: caracterizare
Dr. Sabin Buraga[Link]/~busaco
“[Link]® is a JavaScript runtime
built on Chrome’s V8 JavaScript engine.”
“[Link] uses an event-driven, non-blocking I/O model
that makes it lightweight and efficient.”
[Link]: caracterizare
Dr. Sabin Buraga[Link]/~busaco
“[Link] is designed to build scalable network applications.”
“[Link] is an open-source, cross-platform, JavaScript
runtime environment that executes JavaScript code
outside of a browser.”
“[Link] represents a JavaScript everywhere paradigm.”
[Link]: caracterizare
Dr. Sabin Buraga[Link]/~busaco
Oferă suport pentru cele mai importante
protocoale Web și Internet
HTTP (HyperText Transfer Protocol)
DNS (Domain Name System)
TLS (Transport Layer Security)
functionalități de nivel scăzut (socket-uri TCP)
Ryan Dahl concepe [Link] (2009) – [Link]
rulează pe mașini respectând POSIX + Windows (2011)
Dr. Sabin Buraga[Link]/~busaco
adoptat de industrie (din 2012)
e.g., Cloud9 IDE, eBay, Google, LinkedIn, NASA, Netflix, Walmart
[Link]/@nodejs
[Link] Foundation (2015)
IBM, Intel, Joyent, Microsoft, RedHat, SAP, The Linux Foundation,…
[Link] 18.16 LTS – Long Term Support (12 aprilie 2023)
versiune stabilă actuală pentru uz în producție
[Link] 20.0 (18 aprilie 2023)
versiunea cea mai recentă
[Link]/nodejs/node
[Link]
Dr. Sabin Buraga[Link]/~busaco
Oferă un mediu de execuție în linia de comandă,
pe baza unor biblioteci C++ și a procesorului V8
node [Link]
[Link]
Dr. Sabin Buraga[Link]/~busaco
Permite dezvoltarea de aplicații Web
la nivel de server în limbajul JavaScript
recurge la V8
procesor – compilează + execută codul – ECMAScript
a single threaded execution JS engine
creat de Google, implementat în C++ și JS, disponibil liber
[Link]
[Link]/docs
[Link]
Dr. Sabin Buraga[Link]/~busaco
[Link]
Dr. Sabin Buraga[Link]/~busaco
Permite dezvoltarea de aplicații Web
la nivel de server în limbajul JavaScript
utilizează libluv
bibliotecă multi-platformă disponibilă liber
axată pe efectuarea de operații I/O asincrone
implementare C++
[Link]
[Link]
Dr. Sabin Buraga[Link]/~busaco
“libuv uses a thread pool to make asynchronous file I/O operations
possible, but network I/O is always performed in a single thread,
each loop’s thread”
[Link]/en/v1.x/[Link]
[Link]: caracterizare
Dr. Sabin Buraga[Link]/~busaco
Intern, mediul recurge la
diverse biblioteci open source C sau C++
libuv (asynchronous I/O) – [Link]
c-ares (asynchronous DNS requests) – [Link]
OpenSSL (crypto + SSL/TLS) – [Link]
zlib (compression) – [Link]
V8 (JavaScript engine) – [Link]
[Link]
Dr. Sabin Buraga[Link]/~busaco
[Link]:
Uzual, o aplicație Web caracterizare
realizează un număr mare de
operații – în acest caz, asincrone – de intrare/ieșire
Dr. Sabin Buraga[Link]/~busaco
G. Yeh (2014): [Link]/garyyeh165/basic-understanding-and-implement-of-nodejs
[Link]: caracterizare
Dr. Sabin Buraga[Link]/~busaco
Operațiile de intrare/ieșire sunt asincrone
fiecare cerere (operație) adresată aplicației
– e.g., acces la disc, la rețea, la alt proces – poate avea
atașată o funcție de tratare a unui eveniment specific
evented I/O
cod JS executat de cod JS rulat pe partea
client (browser Web) de server ([Link])
procesare
Dr. Sabin Buraga[Link]/~busaco
așteaptă și tratează
evenimente de bazată pe așteaptă și tratează
interacțiune evenimente cereri (evenimente)
(onclick, onmouseover, evented/ provenite de la client(i)
onkeypressed,…) event-based
programul trebuie să fie programul trebuie să fie
responsiv atunci când responsiv atunci când
așteaptă încărcarea asincronism așteaptă încărcarea
datelor de pe rețea (e.g., operatii datelor locale/externe
(JSON, XML, neblocante) (preluate din baze de
imagini, video etc.) date, fișiere,
via Ajax ori Web sockets servicii Web, API-uri,…)
adaptare după Ben Sheldon (2012)
[Link]: caracterizare
Dr. Sabin Buraga[Link]/~busaco
O aplicație [Link] rulează într-un singur proces
event loop ≡ “an entity that handles & processes external
events and converts them into callback invocations”
[Link]: caracterizare
Dr. Sabin Buraga[Link]/~busaco
O aplicație [Link] rulează într-un singur proces
event loop ≡ “an entity that handles & processes external
events and converts them into callback invocations”
codul JavaScript nu este executat paralel,
dar tratează în mod asincron diverse evenimente I/O
Aplicația [Link] „reacționează” la evenimente
context [Link]: caracterizare
larg: reactive programming – [Link]
Dr. Sabin Buraga[Link]/~busaco
G. Yeh (2014): [Link]/garyyeh165/basic-understanding-and-implement-of-nodejs
[Link]: caracterizare
Dr. Sabin Buraga[Link]/~busaco
O aplicație [Link] rulează într-un singur proces
deosebire esențială față de serverele de aplicații Web
tradiționale ce recurg la servere multi-process/threaded
server Web clasic
cerere mulțimea
📺 ⧁ HTTP: server Web
firelor de
Dr. Sabin Buraga[Link]/~busaco
execuție
(thread pool)
cerere
☎ ⧁ resurse
cereri ⌛ (date/servicii)
💻 ⦷ ⧁ 🖴⎘⎙☁
cereri operații I/O
blocante
⚙️ ⦷ ⦷ ⧁
⧁ în execuție
server Web multi-threaded ⦷ în așteptare
cererile multiple de la diverși clienți nu pot fi deservite simultan
(numărul firelor de execuție asociate unui proces este limitat)
[Link]
cerere event loop
📺 HTTP: server Web
Dr. Sabin Buraga[Link]/~busaco
cerere
☎ resurse
POSIX
⧁ ⟺ async (date/servicii)
cereri
💻 threads 🖴⎘⎙☁
cereri
⧁⧁ operații I/O
neblocante
⚙️ ⧁⧁
⧁ în execuție
server [Link] ⟺ delegare
cererile multiple de la diverși clienți pot fi deservite simultan
[Link]: caracterizare
Dr. Sabin Buraga[Link]/~busaco
Mediul [Link] e disponibil gratuit – open source –
pentru platformele Linux, Windows, macOS
[Link]/en/download/
inclusiv imagini-sistem Docker: [Link]/_/node/
Dr. Sabin Buraga[Link]/~busaco
Funcționalități suplimentare oferite de module
administrate cu Node Package Manager
npm
utilitar în linia de comandă dezvoltat complet în JavaScript
(inițiat de Isaac Z. Schlueter în 2010)
[Link]
[Link]/npm
[Link]: caracterizare
Dr. Sabin Buraga[Link]/~busaco
Utilitarul npm poate gestiona dependențe imbricate
detalii la [Link]
[Link]: exemplu
Dr. Sabin Buraga[Link]/~busaco
Un prim program care emite mesaje de salut
// [Link]: un program (de sine-stătător) care emite un salut
[Link] ('Salutări banale din [Link]');
invocarea unei
metode oferită de
un obiect predefinit
[Link]: exemplu
Dr. Sabin Buraga[Link]/~busaco
Un prim program care emite mesaje de salut
// [Link]: un program (de sine-stătător) care emite un salut
[Link] ('Salutări banale din [Link]');
> node [Link]
Salutări banale din [Link]
/* Un program JavaScript ilustrând comportamentul asincron
al operațiilor I/O implementate de [Link] */
const fs = require ('fs'); // acces la sistemul de fișiere
Dr. Sabin Buraga[Link]/~busaco
[Link] ('[Link]', 'utf-8', function (eroare, date) {
if (eroare)
throw eroare; // excepție de citire
[Link] (date);
})
[Link] ('Gata!');
execuția (cod interpretat) pornește
de la prima linie a programului JavaScript
/* Un program JavaScript ilustrând comportamentul asincron
al operațiilor I/O implementate de [Link] */
const fs = require ('fs'); // acces la sistemul de fișiere
Dr. Sabin Buraga[Link]/~busaco
[Link] ('[Link]', 'utf-8', function (eroare, date) {
if (eroare)
throw eroare; // excepție de citire
[Link] (date);
})
[Link] ('Gata!');
începe execuția unei operații asincrone
(aici, citirea conținutului unui fișier text)
care returnează imediat
/* Un program JavaScript ilustrând comportamentul asincron
al operațiilor I/O implementate de [Link] */
const fs = require ('fs'); // acces la sistemul de fișiere
Dr. Sabin Buraga[Link]/~busaco
[Link] ('[Link]', 'utf-8', function (eroare, date) {
if (eroare)
throw eroare; // excepție de citire
[Link] (date);
})
[Link] ('Gata!');
execuția continuă cu ultima linie de program
> node [Link]
Gata!
/* Un program JavaScript ilustrând comportamentul asincron
al operațiilor I/O implementate de [Link] */
const fs = require ('fs'); // acces la sistemul de fișiere
Dr. Sabin Buraga[Link]/~busaco
[Link] ('[Link]', 'utf-8', function (eroare, date) {
if (eroare)
throw eroare; // excepție de citire
[Link] (date);
})
[Link] ('Gata!');
…după care sunt afișate datele preluate din fișier
> node [Link]
Gata!
Un prim salut...
Acesta este al doilea salut.
// Un program JavaScript care salută toți posibilii săi clienți Web
const http = require ('http'); // folosim 'http', un modul Node predefinit
[Link] ( // creăm un server Web
Dr. Sabin Buraga[Link]/~busaco
// funcție anonimă ce tratează o cerere și trimite un răspuns
function (cerere, raspuns) {
// afișăm la consola serverului mesaje de diagnostic
[Link] ('Am primit o cerere...');
// stabilim valori pentru diverse câmpuri din antetul mesajului HTTP
[Link] (200, { 'Content-Type': 'text/html' });
// emitem răspunsul propriu-zis conform tipului MIME (aici, cod HTML)
[Link] ('<html><body><h1>Salutari…</h1></body></html>');
}
// serverul ascultă cereri la portul 8080 al mașinii locale
).listen (8080, "[Link]");
[Link] ('Serverul creat asteapta cereri la [Link]
programul JavaScript creat funcționează ca un server Web
pentru fiecare cerere emisă de un posibil client (browser,
aplicație desktop etc.) conform modelului client/server
Dr. Sabin Buraga[Link]/~busaco
pe partea de server – așteptare de cereri
> node [Link]
Serverul creat asteapta cereri la [Link]
Am primit o cerere...
Am primit o cerere...
programul JavaScript creat funcționează ca un server Web
pentru fiecare cerere emisă de un posibil client (browser,
aplicație desktop etc.) conform modelului client/server
Dr. Sabin Buraga[Link]/~busaco
pe partea de server – așteptare de cereri
> node [Link]
Serverul creat asteapta cereri la [Link]
Am primit o cerere...
Am primit o cerere...
la client – recepționarea răspunsului conform cererii GET
emise de un program desktop și de un navigator Web
> node [Link]
Am primit raspuns de la server -- cod HTTP: 200
Continut receptionat: <html><body>
<h1>Salutari din [Link]</h1></body></html>
// Un program JS care implementează un client pentru serviciul de salut
const http = require ('http');
[Link] ('[Link] // emite o cerere HTTP
Dr. Sabin Buraga[Link]/~busaco
function (raspuns) {
[Link] ('Am primit raspuns de la server -- cod HTTP: '
+ [Link]); // statusCode: 200, 404,…
})
// tratăm diverse evenimente via funcții (eventual, anonime) de tip callback
.on ('error', // eroare
function (e) { [Link] ('Eroare: ' + [Link]); })
.on ('response', // receptare răspuns de la server
function (raspuns) { // există date de procesat
[Link] ('data', function (date) {
[Link] ('Continut receptionat: ' + date);
});
}
);
// Aceleași acțiuni realizate în ES6
// Implementează un client pentru serviciul de salut
const http = require ('http');
Dr. Sabin Buraga[Link]/~busaco
[Link] ('[Link] // emite o cerere HTTP
raspuns => [Link] ('Am primit raspuns de la server -- cod HTTP: '
+ [Link]) // statusCode: 200, 404,...
)
// tratăm diverse evenimente
.on ('error', e => [Link] ('Eroare: ' + [Link])) // eroare
.on ('response', // receptare răspuns de la server
raspuns => { // există date de procesat
[Link] ('data',
date => [Link] ("Continut receptionat:\n" + date));
[Link] ('Campuri-antet HTTP primite: '
+ [Link]([Link], null, '\t'));
}
);
Dr. Sabin Buraga[Link]/~busaco
> node [Link]
Am primit raspuns de la server -- cod HTTP: 200
Campuri-antet HTTP primite: {
"content-type": "text/html",
"date": "Tue, 25 Apr 2023 [Link] GMT",
"connection": "close",
"transfer-encoding": "chunked"
}
Continut receptionat:
<html><body><h1>Salutari din [Link]</h1></body></html>
[Link]: module
Dr. Sabin Buraga[Link]/~busaco
Funcția require () specifică utilizarea unui modul [Link]
module predefinite (built-in) – exemple:
privitoare la tehnologii Web – http, https, url, querystring
referitoare la fișiere – fs, path
vizând rețeaua – net, dns, dgram, tls,…
resurse privind sistemul de operare – os, child_process
alte aspecte de interes – buffer, console, util, crypto
suport multi-core – cluster
[Link]: module
Dr. Sabin Buraga[Link]/~busaco
documentația online aferentă
[Link]/en/docs/
[Link]/node/
atenție: o parte
dintre funcționalități
[Link]: module sunt experimentale
Dr. Sabin Buraga[Link]/~busaco
[Link]/api/[Link]
[Link]: module – http
Dr. Sabin Buraga[Link]/~busaco
Dezvoltarea de aplicații Web via modulul http
funcționalități HTTP de bază
crearea unui server Web: createServer()
realizarea de cereri HTTP: request() get()
[Link]: module – http
Dr. Sabin Buraga[Link]/~busaco
Dezvoltarea de aplicații Web via modulul http
servire de cereri HTTP – clasa [Link]
metode uzuale:
listen() setTimeout() close()
evenimente ce pot fi tratate:
request connect close clientError etc.
[Link]: module – http
Dr. Sabin Buraga[Link]/~busaco
Dezvoltarea de aplicații Web via modulul http
răspuns emis de server – clasa [Link]
metode uzuale:
writeHead() getHeader() removeHeader() write() end() etc.
evenimente: close finish
proprietăți folositoare: statusCode headersSent
[Link]: module – http
Dr. Sabin Buraga[Link]/~busaco
Dezvoltarea de aplicații Web via modulul http
cerere emisă de client – clasa [Link]
metode uzuale:
write() abort() end() setTimeout() setSocketKeepAlive()
evenimente ce pot fi tratate:
response connect continue socket etc.
[Link]: module – http
Dr. Sabin Buraga[Link]/~busaco
Dezvoltarea de aplicații Web via modulul http
mesaj vehiculat – clasa [Link]
metode: setEncoding() setTimeout() pause() resume()
evenimente ce pot fi tratate: data end close
proprietăți de interes:
httpVersion headers method url statusCode socket
[Link]: module – http
Dr. Sabin Buraga[Link]/~busaco
Suplimentar, pot fi folosite modulele interne:
https – suport pentru HTTPS
[Link]/api/[Link]
http2 – implementează HTTP/2
[Link]/api/[Link]
[Link]: module – url
Dr. Sabin Buraga[Link]/~busaco
Procesarea adreselor Web via modulul url
clase oferite:
URL() URLSearchParams()
[Link]/api/[Link]
let adresaWeb = new URL
('[Link]
[Link] = 'acolo';
Dr. Sabin Buraga[Link]/~busaco
[Link] = 'https';
[Link] (adresaWeb);
// parametrii din query string (valoarea proprietății search)
// sunt încapsulați de obiectul URLSearchParams
let params = new URLSearchParams ([Link]);
if ([Link] ('marime') > 13) {
[Link] ('Jucaria e in regula.');
} else {
[Link] ('Jucaria e stricata.');
}
> node [Link]
URL {
href:
Dr. Sabin Buraga[Link]/~busaco
'[Link]
origin: '[Link]
protocol: 'https:',
username: '',
password: '',
host: 'acolo:8080',
hostname: 'acolo',
port: '8080',
pathname: '/oferta/jucarii/produs/',
search: '?nume=Tux&marime=17',
searchParams: URLSearchParams { 'nume' => 'Tux', 'marime' => '17' },
hash: '#oferta' }
Jucaria e in regula.
[Link]: module – net
Dr. Sabin Buraga[Link]/~busaco
Crearea de aplicații Internet – modulul net
partea de server:
createServer()
+
clasa [Link]
metode: listen() close() address() getConnections()
evenimente: listening connection close error
proprietăți: listening maxConnections
[Link]: module – net
Dr. Sabin Buraga[Link]/~busaco
Crearea de aplicații Internet – modulul net
partea de client:
connect()
createConnection()
[Link]: module – net
Dr. Sabin Buraga[Link]/~busaco
Crearea de aplicații Internet – modulul net
acces la socket-uri – clasa [Link]
metode: connect() write() setEncoding() destroy() end() etc.
evenimente: connect data end timeout drain error close
proprietăți utile: localAddress localPort
remoteAddress remotePort bytesRead bytesWritten bufferSize
[Link]: module – fs
Dr. Sabin Buraga[Link]/~busaco
Acces la sistemul de fișiere via modulul fs
clase importante:
[Link] – flux de citire
[Link] – flux de scriere
[Link] – informații despre un fișier
[Link] – monitorizează schimbările dintr-un fișier
(obiecte de tip EventEmitter – evenimentul change)
[Link] – element dintr-un director (directory entry)
[Link]: module – fs
Dr. Sabin Buraga[Link]/~busaco
Acces la sistemul de fișiere via modulul fs
metode folosite uzual – comportament asincron:
open() read() write() close()
truncate() stat() chmod() rename() unlink() watch()
isFile() isDirectory() isBlockDevice() isSocket()
mkdir() rmdir() readdir()
[Link]: module – fs
Dr. Sabin Buraga[Link]/~busaco
Acces la sistemul de fișiere via modulul fs
unele metode au comportament sincron
(numele lor sunt sufixate cu Sync)
exemple:
openSync() readSync() writeSync() closeSync()
appendFileSync() chmodSync() unlinkSync() mkdirSync()
const http = require ("http");
const url = require ("url"); mini-server Web oferind
const path = require ("path"); fișiere statice stocate în 'public/'
const fs = require ("fs");
[Link] ((cerere, raspuns) => {
Dr. Sabin Buraga[Link]/~busaco
let uri = [Link] ([Link]).pathname; // preluăm URL și calea spre fișierul dorit
let numefis = [Link] ([Link] (), 'public/', uri);
[Link] (numefis, [Link].R_OK, (eroare) => {
if (eroare) { // resursa nu există, trimitem bine-cunoscutul cod 404
[Link] (404, { "Content-Type": "text/plain" });
[Link] ("404 Not Found\n");
[Link] (); // închidem fluxul de date spre client
return;
}
[Link] (numefis, "binary", (eroare, fisier) => { // resursa există, poate fi citită
if (eroare) { // eroare de citire a fisierului, trimitem 500
[Link] (500, { "Content-Type": "text/plain" });
[Link] (eroare + "\n"); [Link] (); return;
}
[Link] (200); // totul e în regulă, trimitem fișierul ca flux binar
[Link] (fisier, "binary");
[Link] ();
});
}); }).listen (8080);
[Link] ('Serverul de fișiere așteaptă cereri la [Link]
Dr. Sabin Buraga[Link]/~busaco
cererea GET de acces a reprezentării resursei de la
[Link] conduce la obținerea
unei imagini în format PNG
(aici, inspecția transferului datelor
cu instrumentele oferite de browser)
[Link]: fluxuri de date
Dr. Sabin Buraga[Link]/~busaco
Accesul la date poate fi realizat
prin intermediul fluxurilor (streams)
abstractizează accesul la date stocate parțial
(partially buffered data)
se emit evenimente ce pot fi tratate de codul aplicației
[Link]: fluxuri de date
Dr. Sabin Buraga[Link]/~busaco
Accesul la date poate fi realizat
prin intermediul fluxurilor (streams)
pot fi citite – [Link]
pot fi scrise – [Link]
duplex (citite și scrise) – [Link]
realizând o transformare a datelor – [Link]
detalii la [Link]/api/[Link]
[Link]: fluxuri de date
Readable Streams Writable Streams
Dr. Sabin Buraga[Link]/~busaco
HTTP response (client) HTTP requests (client)
HTTP requests (server) HTTP responses (server)
fs read streams fs write streams
zlib streams zlib streams
crypto streams crypto streams
TCP sockets TCP sockets
child process stdout & stderr child process stdin
[Link] [Link] [Link]
[Link]/samerbuna/efficient-node
[Link]: fluxuri de date
Dr. Sabin Buraga[Link]/~busaco
Accesul la date poate fi realizat
prin intermediul fluxurilor (streams)
fluxuri ce pot fi citite (readable streams)
e.g., create de [Link]() [Link]
[Link] [Link] [Link] [Link]
[Link]: fluxuri de date
Dr. Sabin Buraga[Link]/~busaco
Accesul la date poate fi realizat
prin intermediul fluxurilor (streams)
fluxuri ce pot fi citite (readable streams)
e.g., create de [Link]() [Link]
[Link] [Link] [Link] [Link]
emit evenimentele readable data end error
[Link]: fluxuri de date
Dr. Sabin Buraga[Link]/~busaco
Accesul la date poate fi realizat
prin intermediul fluxurilor (streams)
fluxuri ce pot fi citite (readable streams)
e.g., create de [Link]() [Link]
[Link] [Link] [Link] [Link]
au asociate metodele pause() resume() destroy()
[Link]: fluxuri de date
Dr. Sabin Buraga[Link]/~busaco
Accesul la date poate fi realizat
prin intermediul fluxurilor (streams)
fluxuri ce pot fi scrise (writeable streams)
e.g., create de [Link]() [Link]
[Link] [Link] [Link] [Link]
[Link]: fluxuri de date
Dr. Sabin Buraga[Link]/~busaco
Accesul la date poate fi realizat
prin intermediul fluxurilor (streams)
fluxuri ce pot fi scrise (writeable streams)
e.g., create de [Link]() [Link]
[Link] [Link] [Link] [Link]
emit evenimentele drain error
[Link]: fluxuri de date
Dr. Sabin Buraga[Link]/~busaco
Accesul la date poate fi realizat
prin intermediul fluxurilor (streams)
fluxuri ce pot fi scrise (writeable streams)
e.g., create de [Link]() [Link]
[Link] [Link] [Link] [Link]
oferă metodele write() end() destroy()
// Program ce preia ceea ce tastează utilizatorul la intrarea standard
// și scrie într-un fișier – adaptare după M. Takada
let fs = require ('fs');
Dr. Sabin Buraga[Link]/~busaco
let fisier = [Link] ('./[Link]');
// la apariția datelor, le scriem în fișier
[Link] ('data', date => [Link] (date));
// tratăm evenimentul de terminare a fluxului
[Link] ('end', () => [Link] ());
// "reactivăm" intrarea standard; implicit, e în starea 'paused'
[Link] ();
obiectul process e global – detalii la [Link]/api/[Link]
[Link]: fluxuri de date
Dr. Sabin Buraga[Link]/~busaco
Accesul la date poate fi realizat
prin intermediul fluxurilor (streams)
exemple de fluxuri de tip duplex:
socket-uri TCP create cu [Link]()
privind arhivele create cu zlib – [Link]/api/[Link]
date criptate via crypto – [Link]/api/[Link]
[Link]: rulare temporizată
Dr. Sabin Buraga[Link]/~busaco
Se poate planifica execuția codului JavaScript
recurgerea la funcțiile globale
setTimeout () clearTimeout () – execuție la un anumit moment
setInterval () clearInterval () – execuție recurentă
setImmediate () clearImmediate () – execuție „imediată”
amănunte la [Link]/api/[Link]
// creăm un server Web care trimite fiecărui client secvența valorilor unui contor
let server = [Link] ().listen (8080, '[Link]');
// stabilim un comportament la apariția evenimentului 'request' (cerere de la un client)
Dr. Sabin Buraga[Link]/~busaco
[Link] ('request', function (cerere, raspuns) {
[Link] ('Cerere de la clientul ' + [Link]['user-agent']);
[Link] (200, { 'Content-Type': 'text/html' });
let contor = 0;
let interval = setInterval ( // generăm valori ale contorului conform intervalului de timp
function () {
[Link] ('<p>Contorul are valoarea ' + contor + '</p>');
[Link] ('Contorul are valoarea ' + contor);
contor++;
if (contor >= 7) {
clearInterval (interval); // ștergem intervalul
[Link] (); // închidem fluxul de răspuns
[Link] ('Am trimis raspuns clientului ' + [Link]['user-agent']);
}
}, 1000); // cod rulat la interval de 1000 milisecunde
});
Cerere de la clientul … Mozilla/5.0 (Windows NT 10.0 …) … Firefox/110.0
Contorul are valoarea 0
Contorul are valoarea 1
Contorul are valoarea 2
Dr. Sabin Buraga[Link]/~busaco
Contorul are valoarea 3
Cerere de la clientul … Edg/112.0.1722.58
Contorul are valoarea 4
Contorul are valoarea 0 codul este rulat
Contorul are valoarea 5
Contorul are valoarea 1
asincron
Contorul are valoarea 6
Am trimis raspuns clientului … Mozilla/5.0 (Windows NT 10.0 …) … Firefox/110.0
Contorul are valoarea 2
Contorul are valoarea 3
Contorul are valoarea 4
Contorul are valoarea 5
Contorul are valoarea 6
Am trimis raspuns clientului … Edg/112.0.1722.58
Cerere de la clientul … Mozilla/5.0 (Windows NT 10.0 …) … Firefox/110.0
Contorul are valoarea 0
Contorul are valoarea 1
Contorul are valoarea 2
Dr. Sabin Buraga[Link]/~busaco
Contorul are valoarea 3
Cerere de la clientul … Edg/112.0.1722.58
Contorul are valoarea 4
Contorul are valoarea 0
Contorul are valoarea 5
Contorul are valoarea 1
Contorul are valoarea 6
Am trimis raspuns clientului … Mozilla/5.0 (Windows NT 10.0 …) … Firefox/110.0
Contorul are valoarea 2
Contorul are valoarea 3
Contorul are valoarea 4
Contorul are valoarea 5
Contorul are valoarea 6
Am trimis raspuns clientului … Edg/112.0.1722.58
browser-ul Web va aștepta ca întreaga secvență de valori
de ce? să fie trimisă de către server
[Link]: evenimente
Dr. Sabin Buraga[Link]/~busaco
Emiterea (lansarea) și tratarea (prinderea)
evenimentelor specificate de programator
se realizează via [Link]
clasă utilizată intern de multe biblioteci de bază
[Link]/api/[Link]
const EventEmitter = require('events');
const cataclism = Symbol('©©©');
class Emițător extends EventEmitter {}
Dr. Sabin Buraga[Link]/~busaco
const emițător = new Emițător(); // un emițător de evenimente
// tratăm evenimentele 'bum' și 'cataclism'
[Link]('bum', () => { [Link]('Bum, bum, bum...'); });
[Link]('cataclism', (e) => { [Link]('Cataclism! ' + [Link]); });
// emitem evenimente (proprii și deja existente)
try {
emiță[Link]('bum');
emiță[Link]('cataclism', new Error([Link]()));
emiță[Link]('error');
} catch (e) {
[Link] ('A survenit o eroare... ' + [Link]);
}
const EventEmitter = require('events');
const cataclism = Symbol('©©©');
class Emițător extends EventEmitter {}
Dr. Sabin Buraga[Link]/~busaco
const emițător = new Emițător(); // un emițător de evenimente
// tratăm evenimentele 'bum' și 'cataclism'
[Link]('bum', () => { [Link]('Bum, bum, bum...'); });
[Link]('cataclism', (e) => { [Link]('Cataclism! ' + [Link]); });
// emitem evenimente (proprii și deja existente)
try {
emiță[Link]('bum');
emiță[Link]('cataclism', new Error([Link]()));
emiță[Link]('error');
} catch (e) {
> node '[Link]
[Link] ('A survenit o eroare... + [Link]);
Bum, bum, bum...
}
Cataclism! Symbol(©©©)
A survenit o eroare... Unhandled error. (undefined)
[Link]: module externe
Dr. Sabin Buraga[Link]/~busaco
Funcția require () specifică utilizarea unui modul [Link]
module disponibile on-line
(instalate și gestionate via utilitarul npm)
tutorial:
[Link]/npm-guide/
[Link]: module externe
Dr. Sabin Buraga[Link]/~busaco
Funcția require () specifică utilizarea unui modul [Link]
instalare globală a unui modul: npm install modul –g
listarea modulelor ce sunt instalate local: npm list
căutarea unui modul: npm search modul
eliminarea unui modul: npm uninstall modul
actualizarea unui modul: npm update modul
amănunte la [Link]
[Link]: module – acces la baze de date
Dr. Sabin Buraga[Link]/~busaco
Operații cu baze de date relaționale SQLite
recurgerea la modulul [Link] via compilatorul emscripten
utilizează o bază de date virtuală stocată în memoria RAM
(importă fișiere SQLite, exportă obiecte typed array)
detalii la [Link]/package/[Link]
[Link]: module – acces la baze de date
Dr. Sabin Buraga[Link]/~busaco
Operații cu baze de date relaționale SQLite
[Link] nu depinde de alte module
actualmente, implementat în WebAssembly (WASM)
[Link]/docs/WebAssembly
exemple demonstrative (interpretor SQL ca aplicație Web):
[Link]/examples/GUI/
[Link]: module – acces la baze de date
Dr. Sabin Buraga[Link]/~busaco
Operații cu baze de date relaționale
Sequalize
acces abstractizat via ORM (Object-Relational Mapping)
pentru servere relaționale: Postgres, MySQL, MariaDB,
SQLite și Microsoft SQL Server
[Link]
[Link]: module – acces la baze de date
Dr. Sabin Buraga[Link]/~busaco
Operații cu baze de date relaționale
alternative ORM la Sequalize:
[Link] – [Link]/[Link]/
bazat pe Knex – a SQL query builder: [Link]
[Link]/mrscx/a-definitive-guide-to-sql-in-nodejs-with-objection-js-knex-part-1-4c2e
[Link] – [Link]
tutorial: [Link]/javascript/bookshelf/
[Link]: module – prelucrări HTML
Dr. Sabin Buraga[Link]/~busaco
Procesarea documentelor HTML
modulul JSDOM conceput integral în JavaScript
simulează comportamentul unui browser Web
și are suport pentru execuție de script-uri JS
util pentru testare și preluarea datelor
din documente HTML (Web scraping)
[Link]/jsdom/jsdom
[Link]: module – prelucrări HTML
Dr. Sabin Buraga[Link]/~busaco
const jsdom = require("jsdom");
const { JSDOM } = jsdom; // acces la obiectul JSDOM oferit de modul
const URL = "[Link]
[Link](URL, { storageQuota: 5000 }) // promite să preia datele
.then(dom => {
[Link]
([Link]("p").textContent);
[Link]([Link]());
})
.catch(eroare => [Link] ('Eroare! ' + [Link]));
[Link]: module – prelucrări HTML
Dr. Sabin Buraga[Link]/~busaco
const jsdom = require("jsdom");
const { JSDOM } = jsdom; // acces la obiectul JSDOM oferit de modul
const URL = "[Link]
[Link](URL, { storageQuota: 5000 }) // promite să preia datele
.then(dom => {
[Link]
([Link]("p").textContent);
[Link]([Link]()); DOM
})
.catch(eroare => [Link] ('Eroare! ' + [Link]));
> node [Link]
fundația unui viitor dezvoltator Web profesionist
[Link]: module – prelucrări HTML
Dr. Sabin Buraga[Link]/~busaco
Procesarea documentelor HTML
alternative la JSDOM:
htmlparser2 – procesor HTML/XML fără validare
[Link]/fb55/htmlparser2
node-html-parser – axat asupra vitezei (DOM simplificat)
[Link]/taoqf/node-html-parser
[Link]: module – prelucrări XML
Dr. Sabin Buraga[Link]/~busaco
Procesarea documentelor XML
fast-xml-parser – procesor XML↔JSON
[Link]/fast-xml-parser/
libxmljs – portarea bibliotecii LibXML
[Link]/libxmljs/
parse-xml – procesor rapid, fără dependențe
[Link]/parse-xml/
Aspecte vizând arhitectura și
ingineria aplicațiilor [Link]?
Dr. Sabin Buraga[Link]/~busaco
[Link]: multithreading
Dr. Sabin Buraga[Link]/~busaco
Actualmente ([Link] 12+), există suport
pentru fire de execuție multiple via modulul worker_threads
utilizări tipice: operații de calcul îndelungate
(CPU-intensive operations)
[Link]/api/worker_threads.html
[Link]/lazy-engineering/node-worker-threads-b57a32d84845
event loop + worker thread pool
Dr. Sabin Buraga[Link]/~busaco
activitățile consumatoare de timp pot fi efectuate de
„lucrători” (workers) – programe JS neinteractive
[Link]/an-intro-to-node-js-that-you-may-have-missed-b175ef4277f7
[Link]: pachete
Dr. Sabin Buraga[Link]/~busaco
Un proiect (aplicație) [Link] compus(ă) din fișiere
multiple poate fi organizat ca un pachet/modul
[Link]: pachete
Dr. Sabin Buraga[Link]/~busaco
[Link]
meta-date (numele pachetului, versiune, autor,…) +
informații privind dependențele de alte module
[Link]/creating-a-package-json-file
{
"name": "WebApp",
[Link]: module – prelucrări HTML
"version": "1.0.0",
"main": "[Link]",
Dr. Sabin Buraga[Link]/~busaco
"dependencies": {
"xml": "^1.0.1", main specifică numele fișie-
"another_dep": "~2.2.0" rului (uzual, [Link]) ce va fi
}, încărcat când modulul este
"devDependencies" : {
"test_framework": "1.0.0 - 1.2.0" solicitat de altă aplicație
}
"keywords": [ "xml", "json" ], poate reprezenta programul
"license": "BSD-2-Clause", principal, executat primul
"author": {
"name": "Tuxy Pinguinnesscool", de mediul de rulare
"email": "tux@[Link]"
},
"description": "…"
}
{
"name": "WebApp",
[Link]: module – prelucrări HTML
"version": "1.0.0",
"main": "[Link]",
Dr. Sabin Buraga[Link]/~busaco
"dependencies": {
"xml": "^1.0.1", dependențele de alte module
"another_dep": "~2.2.0" se declară via dependencies
}, + aspecte vizând versiunea
"devDependencies" : { [Link]/about-semantic-versioning
"test_framework": "1.0.0 - 1.2.0"
}
"keywords": [ "xml", "json" ], devDependencies include
"license": "BSD-2-Clause", dependențele necesare doar
"author": {
"name": "Tuxy Pinguinnesscool", în faza de dezvoltare
"email": "tux@[Link]"
},
"description": "…"
}
[Link]: pachete
Dr. Sabin Buraga[Link]/~busaco
Un pachet poate avea un domeniu de vizibilitate (scope)
[Link]/about-scopes
[Link] poate fi generat automat cu npm init sau
npm init --scope=@organizație
[Link]: pachete
Dr. Sabin Buraga[Link]/~busaco
Pachetele care n-au specificat domeniul de vizibilitate
sunt considerate automat publice
pachetele private trebuie să aibă obligatoriu asociat
un domeniu de vizibilitate
(private packages are always scoped)
[Link]: pachete
Dr. Sabin Buraga[Link]/~busaco
Pentru publicarea în registrul on-line al modulelor NPM
se folosește npm publish
[Link]/cli/publish
[Link]: pachete
Dr. Sabin Buraga[Link]/~busaco
[Link]
generat automat când se modifică arborele de module
(node_modules) sau fișierul [Link]
descrie arborele curent de dependențe al unui proiect
pentru a facilita instalarea și mentenanța
[Link]/files/[Link]
[Link]: pachete
Dr. Sabin Buraga[Link]/~busaco
vezi arhiva
exemplelor
editarea, organizarea și rularea on-line a codului [Link]
cu instrumentul Web Replit – [Link]/languages/nodejs
aici, un program ce transformă date JSON în format XML
pe baza modulului extern xml
[Link]: framework-uri web
Dr. Sabin Buraga[Link]/~busaco
Uzual, încurajează dezvoltarea de aplicații Web
în care interacțiunea cu utilizatorul
se realizează într-o singură pagină
(SPA – Single-Page Applications)
real-time single-page Web apps
Paul Sherman, How Single-Page Applications Work (2018)
[Link]/how-single-page-applications-work/
[Link]: framework-uri web
Dr. Sabin Buraga[Link]/~busaco
Alte facilități notabile:
MVC (Model-View-Controller) și variantele
transfer de date în timp-real – e.g., cu [Link]
servicii Web – REST și/sau GraphQL
suport pentru baze de date (No)SQL
machete de redare a conținutului (templates)
Alex Ivanovs, The Most Popular [Link] Frameworks in 2023
[Link]/node-js-frameworks/
[Link]: framework-uri web – express
Dr. Sabin Buraga[Link]/~busaco
Framework minimalist
ce încurajează dezvoltarea de aplicații Web
tradiționale – reprezentări multiple via hipermedia
bazate pe un unic punct de acces: SPA (Single Page App)
hibride (Web + aplicații native)
[Link]
[Link]/docs/Learn/Server-side/Express_Nodejs
.
├── [Link]
├── bin
│ └── www
├── [Link]
├── public conținut static destinat clientului
Dr. Sabin Buraga[Link]/~busaco
│ ├── images
│ ├── javascripts (e.g., foi de stiluri CSS, biblioteci JS
│ └── stylesheets procesate de browser, imagini,…)
│ └── [Link]
├── routes rute vizând deservirea cererilor pe
│ ├── [Link]
│ └── [Link] baza URL-urilor solicitate de client
└── views specificarea interfeței (view-ul)
├── [Link]
├── [Link] via machete de vizualizare bazate
└── [Link] pe Pug: [Link]
eșafodajul unei aplicații Web bazate pe Express
create cu express --view=pug web-project
implicit, aplicația va putea fi accesată la [Link]
[Link]: framework-uri web
Dr. Sabin Buraga[Link]/~busaco
MEAN (MongoDB, Express, Angular, [Link])
Matthew Martin, What is Mean Stack Developer? (2023)
[Link]/[Link]
[Link]: framework-uri web
Dr. Sabin Buraga[Link]/~busaco
MEAN recurgând la un API REST
[Link]: framework-uri web
Dr. Sabin Buraga[Link]/~busaco
MERN (MongoDB, Express, React, [Link])
tutoriale:
MERN Stack
[Link]/mern-stack
MERN stack A to Z
[Link]/mern-stack-tutorial/
[Link]: framework-uri web
Dr. Sabin Buraga[Link]/~busaco
pentru acces asincron la serverul MongoDB
se poate folosi modulul Mongoose
[Link]
[Link]: framework-uri web
Dr. Sabin Buraga[Link]/~busaco
Alternative/specializări:
Adonis – [Link]/docs/
Fastify – [Link]/docs/latest/
[Link] – [Link]/koajs
Lad – [Link]/ladjs/lad
Loopback – [Link]/doc/
Nanoexpress – [Link]
Nest – [Link]
Sails – [Link]/documentation/concepts
[Link]: framework-uri web
Dr. Sabin Buraga[Link]/~busaco
Implementarea (micro-)serviciilor Web
ghiduri practice:
[Link]/building-microservices-node-js/
[Link]/blog/building-javascript-microservices-node-js
[Link]: utilizări pragmatice
Dr. Sabin Buraga[Link]/~busaco
Deservirea unui volum mare de conexiuni
concurente cu necesar minim de resurse
(procesor, memorie) într-un singur proces
[Link]: utilizări pragmatice
Dr. Sabin Buraga[Link]/~busaco
Procesarea în timp-real
a datelor JSON oferite de API-uri (multiple)
inclusiv, crearea de aplicații
oferind fluxuri de date (streaming data)
context: Internet Web of Things
[Link]: utilizări pragmatice
Dr. Sabin Buraga[Link]/~busaco
Procesarea în timp-real
a datelor JSON oferite de API-uri (multiple)
studii de caz:
[Link]/blog/tag/node-js/
[Link]: utilizări pragmatice
Dr. Sabin Buraga[Link]/~busaco
Dezvoltarea rapidă de servicii Web
sau API-uri conform paradigmei REST
(REpresentational State Transfer) ori GraphQL
framework-uri pentru dezvoltarea de API-uri – exemple:
egg, Hapi, LoopBack, NestJS,
Restgoose, restify, TypeGraphQL
[Link]: utilizări pragmatice
Dr. Sabin Buraga[Link]/~busaco
Crearea de aplicații native (desktop)
folosind tehnologii Web moderne precum HTML5
[Link] (fost node-webkit) – [Link]
utilizarea modulelor [Link]
direct la nivel de DOM via Chromium
[Link]: instrumente de dezvoltare
Dr. Sabin Buraga[Link]/~busaco
Mediu de dezvoltare tradițional (desktop)
exemplificări:
[Link] in Visual Studio Code
[Link]/docs/nodejs/nodejs-tutorial
[Link] Tools for Visual Studio
[Link]/vs/features/node-js/
[Link]: instrumente de dezvoltare
Dr. Sabin Buraga[Link]/~busaco
execuția aplicațiilor [Link] în „nori”: AWS SDK for JS
[Link]/sdk-for-javascript/
[Link]/sdk-for-javascript/
[Link]: instrumente de dezvoltare
Dr. Sabin Buraga[Link]/~busaco
execuția aplicațiilor [Link] în „nori”: Azure SDK for JS
[Link]/en-us/azure/developer/javascript/
Azure Tools for Visual Studio Code
[Link]/microsoft/vscode-node-azure-pack
Dr. Sabin Buraga[Link]/~busaco
execuția aplicațiilor [Link] în „nori”:
[Link] on Google Cloud – [Link]/nodejs/
Dr. Sabin Buraga[Link]/~busaco
execuția aplicațiilor [Link] în „nori”: [Link] on Heroku
[Link]/nodejs
Getting Started on Heroku with [Link]
[Link]/articles/getting-started-with-nodejs
[Link]: instrumente de dezvoltare
Dr. Sabin Buraga[Link]/~busaco
În cazul DigitalOcean, a se explora tutorialele
[Link]/community/tutorials?q=[JavaScript]
[Link]: instrumente de dezvoltare
Dr. Sabin Buraga[Link]/~busaco
În contextul generării statice de conținuturi oferite de
API-uri (JAMstack), a se considera soluții precum Netlify
în conjuncție cu generatoare de situri Web statice
(e.g., Docusaurus, Gatsby, [Link], Nuxt) și sisteme de
management al conținutului (Ghost, Strapi, Webiny,...)
[Link]/generators/
[Link]: alternative
Dr. Sabin Buraga[Link]/~busaco
Deno
a JavaScript, TypeScript, and WebAssembly runtime
built on V8, Rust, and Tokio
[Link]/manual
[Link]: alternative
Dr. Sabin Buraga[Link]/~busaco
Bun
an all-in-one toolkit for JavaScript and TypeScript
designed as a faster, leaner,
more modern replacement for [Link]
[Link]/docs
Câteva studii
de caz concrete…
Dr. Sabin Buraga[Link]/~busaco
[Link]: exemplu – smartfetcher
Dr. Sabin Buraga[Link]/~busaco
Scop: recomandare în timp-real de știri de interes
(ziare, blog-uri,…), pe baza profilului utilizatorului
și a interacțiunii sale cu sistemul
recurge la tehnici de învățare automată, în funcție și
de sentimentul manifestat față de un articol dat
arhitecturi: exemplu – smartfetcher
Dr. Sabin Buraga[Link]/~busaco
la nivel de server (backend): [Link] (framework-ul Sails)
API REST – eventual, folosit via WebSocket-uri
pentru comunicarea în timp-real cu clienții
pe partea client (frontend): Angular și Bootstrap
Dr. Sabin Buraga[Link]/~busaco
proiect de licență al absolvenților Raluca Jalaboi & Bogdan
Spiridon (Facultatea de Informatică, UAIC Iași, 2015)
[Link]: exemplu – muser
Dr. Sabin Buraga[Link]/~busaco
MuSeR (Music Smart Enhancer) – a cross-platform semantic
Web application developed for music lovers able to generate
& manage in a “smart” way favorite playlists
surse de date/cunoștințe externe: DBpedia + Spotify
implementare [Link] bazată pe micro-servicii Web:
Serverless Framework – [Link]
exploatare în „nori” via AWS (Amazon Web Services)
independența de client facilitată de Ionic
Dr. Sabin Buraga[Link]/~busaco
Lila-Ciprian Lazăr, Alexandru Cristea, Dan Cehan
(studii de master @ FII, UAIC Iași, 2017—2018)
[Link]/MuSer/
[Link]: exemplu – harperdb
Dr. Sabin Buraga[Link]/~busaco
HarperDB – sistem scalabil conceput în [Link] pentru
management de baze de date via un API REST: [Link]
[Link]/brief-history-of-how-we-develop-harperdb-pb3z33qr
[Link]: exemplu
Dr. Sabin Buraga[Link]/~busaco
Stive tehnologice (tech stacks) ce includ [Link]
tech stack
desemnează mulțimea tehnologiilor – limbaje,
framework-uri, biblioteci, servere, soluții de interacțiune
cu utilizatorul, utilitare, metodologii etc. – pe care
un producător software le folosește
pentru a dezvolta o aplicație (Web, mobilă,…)
Dr. Sabin Buraga[Link]/~busaco
inspectarea
tehnologiilor folosite
de o aplicație Web
cu instrumentul
WhatRuns
[Link]/ebay/ebay/
[Link]: exemplu
Dr. Sabin Buraga[Link]/~busaco
[Link]: exemplu
[Link]/udemy/udemy/
Dr. Sabin Buraga[Link]/~busaco
[Link]: exemplu
Dr. Sabin Buraga[Link]/~busaco
[Link]/food-and-more/food-and-more/
[Link]: exemplu
Dr. Sabin Buraga[Link]/~busaco
[Link]/bootstrapcdn/bootstrapcdn/
[Link]: alte resurse utile
Dr. Sabin Buraga[Link]/~busaco
Design, Architecture & Best Practices
[Link]/tao-of-node/
[Link]/goldbergyoni/nodebestpractices
[Link]/articles/node-best-practices
Awesome [Link]
[Link]/sindresorhus/awesome-nodejs
Node Weekly
[Link]
#nodejs Stories @ Hacker Noon
[Link]/tagged/nodejs
rezumat
Dr. Sabin Buraga[Link]/~busaco
⍟
dezvoltarea de aplicații Web la nivel de server
cu [Link] – caracteristici, module, exemple