Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
38 views

2 NodeJS

npm is used to install and manage Node.js packages or modules. Some key things about npm: - It comes bundled with Node.js. So when you install Node.js, you automatically get npm. - You can install packages globally (available everywhere on your system) or locally (only in the current project). - Common commands: - npm install <package-name> - Install a package locally - npm install -g <package-name> - Install globally - npm init - Initialize a package.json file - npm update - Update installed packages - npm uninstall <package-name> - Uninstall a package - Packages

Uploaded by

giang nguyễn
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
38 views

2 NodeJS

npm is used to install and manage Node.js packages or modules. Some key things about npm: - It comes bundled with Node.js. So when you install Node.js, you automatically get npm. - You can install packages globally (available everywhere on your system) or locally (only in the current project). - Common commands: - npm install <package-name> - Install a package locally - npm install -g <package-name> - Install globally - npm init - Initialize a package.json file - npm update - Update installed packages - npm uninstall <package-name> - Uninstall a package - Packages

Uploaded by

giang nguyễn
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 118

CT313H:

Web Technologies and Services

Bùi Võ Quốc Bảo


(bvqbao@cit.ctu.edu.vn)

Cần Thơ, 2023


Credit

● The slides are inspired by the CS193X course created by


Victoria Kirst
Servers
Server-side programming

“Client-side" programming:
- The code we write gets run in a browser on the user's
(client's) machine

“Server-side” programming:
- The code we write gets run on a server
- Servers are computers run programs to generate web
pages and other web resources
Recall…
When you navigate to a URL:
- Browser creates an HTTP GET request
- Operating system sends the GET request to the server over TCP
When a server computer receives a message:
- The server's operating system sends the message to the server
software (via a socket)
- The server software then parses the message
- The server software creates an HTTP response
- The server OS sends the HTTP response to the client over TCP

Client Server

(Routing,
etc…)
"Server"

The definition of server is overloaded:


- Sometimes "server" means the machine/computer that
runs the server software.
- Sometimes "server" means the software running on the
machine/computer.
You have to use context to know which is being meant
Sockets

Q: What does it mean for a program to be "listening" for


messages?

When the server first runs, it executes code to create a


socket that allows it to receive incoming messages from
the OS
A socket is one end of a communication channel. You can
send and receive data on sockets

However, NodeJS will abstract this away so we don't have


to think about sockets
Servers

Sometimes when you type a URL in your browser,


the URL is a path to a file on the internet:
- Your browser connects to the host address
and requests the given file over HTTP
- The web server software (e.g. Apache) grabs
that file from the server's local file system,
and sends back its contents to you

But that's not always the case


Web Services

Other times when you type a URL into your


browser, the URL represents an API endpoint,
and not a path to a file
That is:
- The web server does not grab a file from
the local file system, and the URL is not
specifying where a file is located
- Rather, the URL represents a
parameterized request, and the web
server dynamically generates a response
to that request
NodeJS
NodeJS

NodeJS:
- A JavaScript runtime written in C++
- Can interpret and execute JavaScript
- Includes support for the NodeJS API

NodeJS API:
- A set of JavaScript libraries that are useful for creating
server programs

V8 (from Chrome):
- The JavaScript interpreter ("engine") that NodeJS uses
to interpret, compile, and execute JavaScript code
NodeJS

NodeJS:
- A JavaScript runtime written in C++
Q: What does
- Can interpret and execute JavaScript this mean?
- Includes support for the NodeJS API

NodeJS API:
- A set of JavaScript libraries that are useful for creating
server programs

V8 (from Chrome):
- The JavaScript interpreter ("engine") that NodeJS uses
to interpret, compile, and execute JavaScript code
First: Chrome

Chrome:
- A browser written in C++
- Can interpret and execute JavaScript code
- Includes support for the DOM APIs

DOM APIs:
- JavaScript libraries to interact with a web page

V8:
- The JavaScript interpreter ("engine") that Chrome uses
to interpret, compile, and execute JavaScript code
Chrome, V8, DOM

Parser
JavaScript DOM API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector
Parser
JavaScript DOM API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector

const name = 'V8';


"Please execute
console.log()"

Parser
JavaScript DOM API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector

console.log('V8');
NodeJS, V8, NodeJS APIs

Parser
JavaScript NodeJS API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector
Parser
JavaScript NodeJS API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector

const x = 15;
x++;
"Please execute
http
.createServer()"

Parser
JavaScript NodeJS API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector

http.createServer();
Parser
JavaScript NodeJS API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector

What if you tried to call


document.querySelector('div');
in the NodeJS runtime?
Parser
JavaScript NodeJS API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector

document.querySelector('div');
ReferenceError: document is not defined
Parser
JavaScript NodeJS API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector

What if you tried to call console.log('nodejs');


in the NodeJS runtime?
"Please execute
console.log()"

Parser
JavaScript NodeJS API
Execution runtime Implementation
Engine
(Call stack,
Garbage memory, etc.)
Collector

console.log('nodejs');

(NodeJS API implemented their own console.log)


NodeJS

NodeJS:
- A JavaScript runtime written in C++
- Can interpret and execute JavaScript
- Includes support for the NodeJS API

NodeJS API:
- A set of JavaScript libraries that are useful for creating
server programs

V8 (from Chrome):
- The JavaScript interpreter ("engine") that NodeJS uses
to interpret, compile, and execute JavaScript code
Installation

NodeJS installation:
- https://nodejs.org/en/download/
- https://github.com/nvm-sh/nvm
- https://github.com/coreybutler/nvm-windows
node command

Running node without a filename runs a read-eval-print


loop (REPL)
- Similar to the JavaScript console in Chrome, or when
you run "python"

$ node
> let x = 5;
undefined
> x++
5
> x
6
NodeJS

NodeJS can be used for writing scripts in JavaScript,


completely unrelated to servers

simple-script.js
function printPoem() {
console.log('Roses are red,');
console.log('Violets are blue,');
console.log('Sugar is sweet,');
console.log('And so are you.');
console.log();
}

printPoem();
printPoem();
node command

The node command can be used to execute a JS file:


$ node fileName

$ node simple-script.js
Roses are red,
Violets are blue,
Sugar is sweet,
And so are you.

Roses are red,


Violets are blue,
Sugar is sweet,
And so are you.
Node for servers

Here is a very basic server written for NodeJS:

(WARNING: We will not actually be writing servers like this!!!


We will be using ExpressJS to help, but we haven't gotten there yet
require()

const http = require('http');


const server = http.createServer();

The NodeJS require() statement loads a module, similar


to import in Java or include in C/C++
- We can require() modules included with NodeJS, or
modules we've written ourselves
- In this example, 'http' is referring to the HTTP
NodeJS module
require()

const http = require('http');


const server = http.createServer();

The http variable returned by require('http') can be


used to make calls to the HTTP API:
- http.createServer() creates a Server object
EventEmitter.on

The on() function is the NodeJS equivalent of


addEventListener
EventEmitter.on

The request event is emitted each time there is a new


HTTP request for the NodeJS program to process

Server
EventEmitter.on

The req parameter gives information about the incoming


request, and the res parameter is the response parameter
that we write to via method calls
- statusCode: Sets the HTTP status code
- setHeader(): Sets the HTTP headers
- end(): Writes the message to the response body then
signals to the server that the message is complete
listen() and listening

The listen() function will make the program start


accepting messages sent to the given port number
- The listening event will be emitted when the server
has been bound to a port
Running the server

When we run node server.js in the terminal, we see


the following:

The process does not end after we run the command, as it is


now waiting for HTTP requests on port 3000
Server response

Here is the result of the request to our HTTP server:


Node for servers

This server
returns the same
response no
matter what the
request is
Node for servers

The NodeJS server APIs


are actually pretty low-
level:
- You build the
request manually
- You write the
response manually
- There's a lot of
tedious processing
code
Express

We're going to use a library called Express on top of


NodeJS:
Express routing
Express

However, Express is not part of the NodeJS APIs


If we try to use it like this, we'll get an error:

We need to install Express via npm


npm

When you install NodeJS, you also install npm:


- npm: Node Package Manager*:
Command-line tool that lets you install packages
(libraries and tools) written in JavaScript and
compatible with NodeJS
- Can find packages through the online repository:
https://www.npmjs.com/

*though the creators of "npm" say it's not an


acronym (as a joke -_-)
npm install and uninstall

npm install package-name


- This downloads the package-name library into a
node_modules folder
- Now the package-name library can be included in your
NodeJS JavaScript files

npm uninstall package-name


- This removes the package-name library from the
node_modules folder, deleting the folder if necessary
Express example

$ npm install express


$ node server.js
Example app listening on port 3000!
Express routes

You can specify routes in Express:


Express routes

app.method(path, handler)
- Specifies how the server should handle HTTP method
requests made to URL/path
- This example is saying:
• When there's a GET request to
http://localhost:3000/hello, respond with the text
"GET hello!"
Handler parameters

Express has its own Request and Response objects:


- req is a Request object
- res is a Response object
- res.send() sends an HTTP response with the given
content
• Sends content type "text/html" by default
Querying our server
HTTP requests

Our server is written to respond to HTTP requests (GitHub):

Q: How do we sent HTTP requests to our server?


Querying our server

Here are four ways to send HTTP requests to our server:

1. Navigate to http://localhost:3000/<path> in our browser


− Caveat: Can only do GET requests

2. Postman Web/HTTP API client

3. curl command-line tool

4. Call fetch() in web page


Postman

https://www.postman.com/
curl

curl: Command-line tool to send and receive data from a


server (Manual)

curl –d '…' –H '…' -X METHOD url

e.g.

$ curl -X GET http://localhost:3000/


Querying with fetch()

JavaScript client
code in a web page:
fetch() to localhost

But if we try fetching to localhost from file://

We get this CORS error:


CORS

CORS: Cross-Origin Resource Sharing (wiki)


- Browser policy for what resources a web page can load
- An origin = protocol + host + port
- You cannot make cross-origin requests by default for:
• Resources loaded via fetch() or XHR

The problem is that we are trying to fetch()


http://localhost:3000 from file:///
- Since the two resources have different origins, this is
disallowed by default CORS policy
CORS

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
Cross-origin solutions

The problem is that we are trying to fetch()


http://localhost:3000 from file:///

Two ways to solve this:


1. Change the server running on localhost:3000 to
allow cross-origin requests, i.e. to allow requests
from different origins (such as file:///)

2. Preferred solution: Load the frontend code statically


from the same server, so that the request is from the
same origin
Solution 1: Enable CORS

You can set an Access-Control-Allow-Origin HTTP header


before sending your response
- This is the server saying to the browser in its response:
"Hey browser, I'm totally fine with websites of any origin
requesting this file"
Solution 1: Enable CORS

Now the fetch will succeed:


Cross-origin solutions

However, you wouldn't have to enable CORS at all if you


were making requests from the same origin

Preferred solution: Load the frontend code statically


from the same server, so that the request is from the
same origin
Recall: Web services

Sometimes when you type a URL into your


browser, the URL represents an API endpoint

That is, the URL represents a parameterized


request, and the web server dynamically
generates a response to that request

That's how our NodeJS server treats routes


defined like this:
Recall: Servers

Other times when you type a URL in your


browser, the URL is a path to a file on the hard
drive of the server:
- The web server software grabs that file from
the server's local file system, and sends back
its contents to you

We can make our NodeJS server also sometimes serve files


"statically," meaning instead of treating all URLs as API
endpoints, some URLs will be treated as file paths
Solution 2: Statically served files

This line of code makes our server now start serving the
files in the 'public' directory directly
Server static data

Now Express will serve:


http://localhost:3000/fetch.html
http://localhost:3000/fetch.js

Express looks up the files relative to the static directory, so


the name of the static directory ("public" in this case) is not
part of the URL
Sending data to the server
Route parameters

A parameter defined in the URL of the request is often called a


"route parameter"

Example:
https://jsonplaceholder.typicode.com/users/10

The last part of the URL is a parameter representing the user


id, which is 10
Route parameters

Q: How do we read route parameters in our server?

A: We can use the :variableName syntax in the path to


specify a route parameter (Express docs):

We can access the route parameters via req.params


Route parameters
Route parameters

You can define multiple route parameters in a URL (docs):


Query parameters

Example:
https://jsonplaceholder.typicode.com/posts?userId=1

The query parameter sent to the server endpoint is userId,


whose value is 1
Query parameters

Q: How do we read query parameters in our server?


A: We can access query parameters via req.query:
POST message body
POST message body

Content-Type: application/json
{"name": "Bao Bui", "email": "bao@example.com"}

Content-Type: application/x-www-form-urlencoded
name=Bao%20Bui&email=bao%40example.com
POST message body
POST message body

$ curl -d '{"name":"Bao Bui", "email":"bao@example.com"}'


-H 'Content-Type: application/json' -X POST
http://localhost:3000/hello
POST message body

$ curl --data-urlencode 'name=Bao Bui' --data-urlencode


'email=bao@example.com' -H 'Content-Type:
application/x-www-form-urlencoded' -X POST
http://localhost:3000/hello
POST message body

HTTP Response Message


Recap

You can deliver parameterized information to the server in


the following ways:

1. Route parameters
2. GET request with query parameters
(DISCOURAGED: POST with query parameters)
3. POST request with message body

Q: When do you use route parameters vs query


parameters vs message body?
GET vs POST

● Use GET requests for retrieving data, not writing data

● Use POST requests for writing data, not retrieving data


You can also use more specific HTTP methods:
○ PUT/PATCH: Updates the specified resource
○ DELETE: Deletes the specified resource

There's nothing technically preventing you from breaking


these rules, but you should use the HTTP methods for their
intended purpose
Route params vs Query params

Generally follow these rules:


● Use route parameters for required parameters for the
request
● Use query parameters for:
○ Optional parameters
○ Parameters whose values can have spaces

These are conventions and are not technically enforced,


nor are they followed by every HTTP API

Also note that query and route parameters are all strings
Middleware
Middleware

Middlewares
Middleware

The middleware stack follows the order of


middlewares placed in the code

*Nguồn: https://iq.opengenus.org/middlewares-in-express/
Middleware

function(req, res, next) { ... };

Middleware functions can perform the following tasks:

− Execute any code


− Make changes to the request and the response objects
− End the request-response cycle
− Call the next middleware in the stack
Middleware

Types of middleware:

− Application-level middleware
− Router-level middleware
− Error handling middleware
− Built-in middleware
− External middleware (requires npm install)
Middleware

Application-level middleware: bound to the app instance


by using app.use() or app.METHOD() functions
Middleware

Application-level middleware: bound to the app instance


by using app.use() or app.METHOD() functions
Middleware

Application-level middleware
Middleware

Router-level middleware: bound to an instance of


express.Router()
Middleware

Router-level middleware: bound to an instance of


express.Router()
Middleware

Error handling middleware: defined last, after other app.use()


and routes calls
Middleware

Built-in middleware

− express.static(): serves static assets (HTML files,


images,…)

− express.json(): parses incoming requests with JSON


payloads (Express >= 4.16.0)

− express.urlencoded(): parses incoming requests with


URL-encoded payloads (Express >= 4.16.0)
Middleware

(Some) External middleware

− morgan: HTTP request logger middleware for node.js

− cors: middleware that can be used to enable CORS with


various options

− cookie-parser: parses Cookie header and populates


req.cookies with an object keyed by the cookie

− multer: middleware for handling multipart/form-data


(file uploads)
Middleware

(Some) External middleware

npm install –D morgan

const morgan = require("morgan");


app.use(morgan("dev"));
package.json
Installing dependencies

In our examples, we had to install the Express npm


packages

$ npm install express

These get written to the node_modules directory


Uploading server code

When you upload NodeJS code to a GitHub repository (or


any code repository), you should not upload the
node_modules directory:
- You shouldn't be modifying code in the node_modules
directory, so there's no reason to have it under version
control
- This will also increase your repo size significantly

Q: But if you don't upload the node_modules directory to


your code repository, how will anyone know what
libraries they need to install?
Managing dependencies

If we don't include the node_modules directory in our


repository, we need to somehow tell other people what
npm modules they need to install

npm provides a mechanism for this: package.json


package.json

You can put a file named package.json in the root directory of


your NodeJS project to specify metadata about your project

Create a package.json file using the following command:


$ npm init

This will ask you a series of questions then generate a


package.json file based on your answers
- Add -y option to get a package.json file with default values
Auto-generated package.json
Saving deps to package.json

Now when you install packages:

$ npm install express


Or
$ npm i express

An entry for this library is added in package.json


Saving deps to package.json

If you remove the node_modules directory:


$ rm -rf node_modules

You can install your project dependencies again via:


$ npm install

- This also allows people who have downloaded your code from
GitHub to install all your dependencies with one command instead
of having to install all dependencies individually
package-lock.json

package-lock.json is auto generated for any operations where


npm modifies either the node_modules tree, or package.json

It describes the exact tree that was generated


npm scripts

Your package.json file also defines scripts:

You can run these scripts using $ npm [run] scriptName

E.g. the following command runs "node server.js"


$ npm start
nodemon

Automatically restart the node application when file changes

$ npm i -D nodemon

-D option: package will appear in devDependencies section

dependencies: packages required to run


devDependencies: only for development

npm install: install packages listed in both sections


npm install --production: only packages in dependencies
are installed
nodemon

Automatically restart the node application when file changes

In package.json, use nodemon to start the server:

"scripts": {
"start": "nodemon server.js"
}

Then run $ npm start


npx: an npm package runner

npx makes it easy to use CLI tools and other executables


hosted on the registry

Using locally-installed tools without npm run-script:


$ npm i –D cowsay
$ npx cowsay hello!

Executing one-off commands:


$ npx cowsay hello!
Node.js Event Loop
Event loop
There are two types of threads in Nodejs:
− One Event Loop (aka the main loop, main thread, event
thread, etc.)
• Responsible for callbacks and non-blocking I/O (i.e.,
network I/O)
• All incoming requests and outgoing responses pass
through the Event Loop

− A pool of k (k=4 by default) Workers in a Worker Pool


(aka the threadpool)
• Handle I/O intensive tasks (dns, file APIs) or CPU-
intensive ones (crypto, zlib APIs)
Event loop

https://blog.insiderattack.net/event-loop-and-the-big-picture-nodejs-event-loop-part-1-1cb67a182810
Event loop

− All user-written synchronous JavaScript code takes priority


over async code that the runtime would like to execute
• Only after the call stack is empty does the event loop
come into play

− Every microtask queue (process.nextTick, resolved Promises)


is visited and emptied after every macrotask (setImmediate,
setTimeout,…)
Event loop

https://techva.me/callback-functions-promises-nodejs/
setTimeout

To help us understand the event loop better, let's learn


about a new command, setTimeout:

setTimeout(function, delay);
- function will fire after delay milliseconds
JS execution

Call stack: JavaScript runtime call stack. Executes the JavaScript


commands, functions
JS execution

Task Queue: When Node.js APIs notice a callback from something


like setTimeout should be fired, it creates a Task and enqueues it
in the Task Queue
JS execution

Event loop: Processes the task queues


- When the call stack is empty, the event loop pulls the next task
from the task queues and puts it on the call stack
JS execution

https://symphony.is/blog/secret-life-event-loop-meetup-overview

You might also like