- Is a developer who is comfortable working with both front-end and back-end technologies.
- Can create full-stack applications by writing code that runs in both a client, such as browser, and a web server.
- Will often specialize in front-end or back-end technologies.
- The terms client and server can refer both a physical device (computer, tablet, phone, etc.) but can also refer to a software process. For example:
- Database softwaresuch as PostgreSQL and web server like Apache are examples of software clients.
- Physical servers connected to the internet are also referred to as host
- We developers usually think of a "web browser" when hear "client".
- Note that durig development, your computer will plays the role of BOTH client and server.
- The PostgreSQL and MongoDB database servers will also be running on your computer, however, we will move to a cloud base MongoDB server as soon as it's pratical.
- Hypertext Transfer Protocol (HTTP) is an application-level network protocol that powers the communication across the World Wide Web.
- HTTP is fundamental to web development - regardless of which back-end or front-end web technology/framework is used.
- When a user interacts with an amazing web application we developed, it's HTTP that informs the web application what the browser wants and it's HTTP that delivers the goods from the server back to the browser.
- The process of a client sending a HTTP request, and server responding is known as the HTTTP Request/Response Cycle:
- When we browse to a website by typing in the address bar, this is what happens:
- Whe the response is received by the client, that request/response cycle has ended and there will be no further HTTP communications unless another request is sent by the client.
- The fact that a connection is not maintained between the client and server makes HTTP a stateless protocol. In other words, the current request does not know what has been done in previous requests.
-
The Status Code alwyas has a three-digit numer that falls within the following range/categories:
- 1xx informational
- 2xx Sucess
- 3xx Redirection
- 4xx Client Error
- 5xx Server Error
- A HTTP request beggins with a request-line like this:
GET /sample_page.html HTTP/1.1
-
The two key components of any HTTP request are:
- The HTTP method (
GET
in the example above), and - The request target, which is usually a URL
- The HTTP method (
- HTTP methods, are used to indicate the desired action to be performed for a given resource (specified by the URL) on the server.
- The fact that they indicate action is why they are also at times called HTTP Verbs
- We'll be using the following HTTP methods when we start "designing" our application's routes.
HTTP Method (Verb) | Desired Action on Server |
---|---|
GET | The GET method requests a representation of the specified resource (URL). Requests using GET should only retrieve data. |
POST | The POST method is used to create a resource on the server. |
PATCH/PUT | The PATCH/PUT method updates a resource with the request payload(data in the body). |
DELETE | The DELETE method deletes the specified resource. |
- URL stands for Uniform Resource Locator
- It informs the server of what resource the client want to GET, create (POST), DELETE, etc.
- Node.js is a runtime enviroment for executing JavaScript outside of the browser.
- Uses the same V8 JavaScript Engine used in the Chrome browser to compile JS programs into machine code.
- Node's runtime enviroment for JS is different than that in the browser, primarily because:
- It doesn't have a browser's DOM or Web API
- Node has low-level networking and file system API that browser JS doesn't (for security reasons).
- In addition to beging used to build high-performance web applications, Node is also a grate tool for building command-tools.
- Node is an open source project governed by the Node.js Foundation with board representation from companies such as:
- PayPal
- Microsoft
- GoDaddy
- IBM
- Red Hat
- Intel
- Node is very "lightweight", i.e., only low-level "core" modules for networking, filesystem access, etc. are baked-in.
- Node's functionality is extented via open source libraries called packages.
- Node's package ecosystem is the largest open source ecosystem in the world.
- REPL is an acronym for Read-Evaluate-Print-Loop
- Programming languages such as Python and Ruby also have REPLs.
- To start Node's interactive REPL we just type
node
in terminal.
- First and foremost, performance - businesses can handle more traffic with less hardware!
- Secondly, developer synergy. Developers can use JavaScript on both client & server, thus becoming a full-stack dev is more obtainable and companies can better utilize their developer resources across the front and back-ends.
- The improvements in server performance and developer productivity result in businesses saving money.
- Businesses saving money results in wide adoption.
- Most importantly, wide adoption of Node.js results in strong demand for Node developers!
- First, it's important to understand how time consuming ("expensive") Input/Output operations are:
- Node's Asynchronous / Event-driven design enables non-blocking Input/Output:
- A typical Node server is capable of supporting tens of thousands of concurrent connections!
- For more information regarding perfomance, check the references at the end of this presentation.
- High-performance, non-blocking I/O operations must be designed as asynchronous methods.
- Therefore, a Node developer will use callback functions and/or promises extensively.
-
Modules in Node allow us to modularize and reuse code in a Node app.
-
Node itself comes with several core modules, such as the
http
andfs
modules. -
There are thousands of open-source modules available.
-
In a Node application, every JavaScript file is a module!
-
A Node app's modules (files) can be put in any folder within the project.
-
This allows us to create modules inside of aptly named folders, such as
models
,routes
,controllers
,views
, etc. -
A module is "loaded" into a Node app using the
require
function we just used to load thefs
module. -
Whatever functionality the module "exports" is returned by the
require
function. -
Since modules are about code reuse, they can be required an unlimited number of times throughout the application.
-
However, the code in the module only runs the first time the module is required.
-
The property on
module
that we're really interested in though isexports
. What value is it initialized to? -
Whatever value is assigned to
module.exports
within a module, is what therequire
function returns!
-
Node uses a package management system to distribute open-source packages called Node Package Manager (npm).
-
Usually a package distributes a Node module, however, sometimes the package distributes a CLI instead of a module we would use in our program.
-
Node programs use a
package.json
file that tracks the installed modules that the app depends upon. -
Tracking an application's dependencies in
package.json
removes the necessity to push the app's node modules to the projects GitHub repo - this saves MASSIVE file storage and bandwidth. -
If you start a Node app from scratch, the first thing you should do is create the package.json file by entering the following command:
npm init
- It's okay to accept all of the default settings. To accept the defaults without being prompted, you can run the command as follows:
npm init -y
- There is now a
node_modules
folder that contains a folder for therequest
module and its many dependencies. - There's also a new
package-lock.json
file that npm uses to track dependencies and unlikepackage.json
, should not be edited. - Note: it's highly recommended that
node_modules
be added to your.gitignore
file.
// Don't specify path when module is in node_modules
const request = require('request');
request(
'http://isitbeeroclock.com',
(err, res, body) => {
console.log(body);
}
);
- Note the first parameter in the callback is
err
. - This "error-first" callback signature is prevalent throughout Node.
-
- Create a
package.json
using the command:
- Create a
npm init
- Accept the default, except for the entry point - set this to be "server.js"
-
Web application frameworks have three capabilities fundamental to writing a back-end web application:
- The ability to define routes
- The ability to process HTTP requests using middleware
- The ability to use a view engine to render dynamic templates
-
Express is the most popular web framework for Node.js.
-
It is minimalistic and lightweight, especially when compared to massie frameworks like Django and Rails.
-
Express uses Node's built-in HTTP module to listen for, and respond to, HTTP requests - Express simply adds those three web application capabalities on top of Node.
-
- Install the Express Module
npm i expres
- Create a
server.js
to put our web app's main code in:
touch server.js
// Load express
const express = require('express');
// Create our express app
const app = express();
// Define a "root" route directly on app
// Tomorrow, we'll use best practice routing
app.get('/', (request, response) => {
response.send('<h1>Hello World!</h1>');
});
// Tell the app to listen on port 3000
// for HTTP requests from clients
app.listen(3000, () => {
console.log('Listening on port 3000');
});
-
The
send
method is a general purpose way to respond to the request, however, soon we'll be using more specific methods. -
- Run the app
node server
-
Browsing to
localhost:3000
will hit out app's root route that we defined and return "Hello World". -
- Nodemon
-
nodemon
is a popular development tool used for automatically restarting our Express app when we save changes.
npm i -g nodemon
-
Command line tools are installed using the -g (global) option
-
Now, thanks to the
main
key inpackage.json
, we can start the server by simply typingnodemon
. -
- First Route
// Mount routes
app.get('/', (request, response) => {
response.send('<h1>Hello Express</h1>');
});
- Like most web frameworks, Express uses the
HTTP Method
and thePath
of the HTTP request to match a route defined in the application. - In our first route, we defined a route using the
get
method on the Expressapp
object. - The
get
method defines a route that listens for aGET
request. There are other methods such aspost
,put
anddelete
, that map to the other HTTP verbs. - The first argument provided to
app.get
,/
, defines the path for the route. In this case the root of the application, i.e., just the host name likelocalhost:3000
. - In Express, all strings used to define a path should start with a forward-slash character (
/
). - In tomorrow's Express lesson, we'll learn a preferred way of defining routes using the Express
Router
object, but you need to be aware of defining routes this way as well. - The second argument provided to
app.get()
is a callback function:
app.get('/', (request, response) => {
response.send('<h1>Hello Express</h1>');
});
- Express will execute route's callback function only when a matching HTTP request (HTTP Method + Path) is received.
- The route's callback function defines two parameters:
request
andresponse
request
: Represents Express's request object, andresponse
: Represents Express's response object
- Express provides those two objects as arguments when it invokes the callback.
- The
request
object has properties and methods used to access information regarding the current HTTP request, including any data being sent from the browser. - The
response
object contains properties and methods used to end the request/response cycle - like we've done so far using theresponse.send
method.
- So far we have responded in our route handler (callback) code by using the
response.send
method. - The Express Docs for the Reponse Object explains the other ways to respond to the HTTP request.
- Here are the methods we'll use the most:
response.render()
- Render a view template and send the resulting HTML to the browser.response.redirect()
- Tell the browser to issue anotherGET
request.response.json()
- Send a JSON response (used when we communicate via AJAX).
- Another of the three fundamental capabilities of a web framework is to be able to use a view engine to render templates.
- A template can include mixture of static HTML and "code" that generates HTML dynamically.
- In Express, we use
response.render
to process a template using a view engine and return the resulting HTML to the browser. - Express can work with a multitude of view egines.
- Pug (formerly
Jade
) is a template language that leverages indentation to create HTML with a "shorthand" syntax. - Exprss applications are usually architeted using the MVC design pattern, so we will put all view templates inside of a
views
folder .ejs
is the file extension for the EJS view engine.
*Let's refactor the GET/Home
route's callback to render our new home.ejs
template:
app.get('/home', (request, response) => {
response.render('home');
});
-
Just the file name, not the
ejs
extension. -
The
app.set
method is used to configure and Express app's settings
// Configure the app (app.set)
app.set ("view engine", "ejs");
- We also need to tell Express where all of our views can be found:
// Configure the app (app.set)
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
-
path.join
is just a Node method that builds a properly formatted path from segment strings passed to it.__dirname
is always available and represent the path of the current folder where the currently running code lives; andviews
is the name of the folder we created to hold our views. -
path
is a core Node module, but it still must be required before we can use it. -
Core Node modules don't have to be installed, but we do need to
require
them.
// Require modules
const express = require('express');
const path = require('path');
- We need to install EJS view engine package:
npm i ejs
-
We don't need to
require
the view engine - Express knows how to find it. -
View engines are used to dynamically generate HTML on the server before sending it to the client.
-
We just used to
render
method, passing in the view name as an argument. -
We can also pass in a JavaScript object as a second argument, and all its properties will be accessible in the view within
ejs
tags.
- View engines are used to dynamically generate HTML, on the server before sending it to the cliente.
- We just use the
render
method, passing in the view name as an argument. - We can also pass in a JavaScript object as a second argument, and all its properties will be accessible in the view within
ejs
tags.
- Now let's code the
todos/index.ejs
view. Start by copying over the HTML fromhome.ejs
and fix it up to look like this:
<body>
<h1>Todos</h1>
<ul>
<% todos.forEach( (t) => { %>
<li>
<%= t.todo %>
-
<%= t.done ? 'done' : 'not done' %>
</li>
<% }); %>
</ul>
</body>
- The
<% %>
EJS tags are for executing JavaScript such as control flow. - The
<%= %>
EJS tags are for writing JS expressions into the HTML page.
*Refactor the root route as follows:
app.get('/', (request, response) => {
response.redirect('/home');
});
- Redirects tell the browser to make a new
GET
request to the providedpath
. - when we start creating, updating, or deleting data, we will always perform a
redirect
.