Express
- An NPM package which comes with a bunch of methods and optional plugins that we can use to build web applications and APIs
- Fast, unopinionated, minimalist web framework for Node.js
- Start up a server to listen for requests
- Parse income requrests
- Match those requests to particular routes
- Craft our http response and associated content
Library vs. Framework
- Library: The user controls the flow of the application code, and decides when to use the library. More flexible
- Framework : The framework controls the user's behavior. (i.e. tells the user where to plug in the code) Less flexible.
How to use Express to make a server
- Terminal : download express
- npm i express
- JS file
const express = require('express');
const app = express();
//Runs whenever the server has an incoming request
app.use(callback);
//Runs whenever the server starts (when it's 'listening')
app.listen(port, callback);
//port : number to identify server(localhost)
//Runs whenever the server has an incoming request with matching path.
//get, post : HTTP verbs
app.get(path, callback);
app.post(path, callback);
- HTTP request : gets only one response each time.
Request & Response Objects
- Express makes them automatically for every incoming request for the server.
- We have access to two different parameters in the callback function of app methods that are automatically passed in.
- Example: app.use((req, res) => { code })
- Express creates JS request object automatically by passing the incoming HTTP request information and then it passes it in as the first argument of the callback function of app methods.
- Response object has methods on it.
- res.send(param) : Sends the HTTP response. Parameter can be a String, Array, JS Object, etc.
Routing
- Taking incoming requests and a path that it requested and match them to some code in some response.
- app.get(path, callback)
- Runs the callback whenever a request comes in matching the path.
- Example : app.get('/cats', (req, res) => {res.send('<h1>MEOW</h1>')};
- To include every possible paths, use '*' (Remember to put this code as the last app.get function, so that other get functions can run if there's matching path)
:
- Matches any path that follows the pattern
- Example
//matches any path that starts with '/r/', but with no additional '/'
//the path after ':' is stored in 'req.params' as an object.
app.get('/r/:subreddit', (req, res) => {
const {subreddit} = req.params;
res.send(`Browsing the ${subreddit} subreddit`);
})
//can match more than one parameter
app.get('/r/:subreddit/:postId', callback);
Query String
- A portion of the RUL that comes after a '?'
- We can include information in key-value pairs as part of the query string.
- Example
- http://mdn.org/search?q=colors
- req.query = {q: 'colors'}
Nodemon
- Watches for changes of the files and restarts the server whenever necessary.
- Install globally through terminal : npm i -g nodemon
- Instead of 'node index.js', use 'nodemon index.js'
HTML with Templating (EJS)
Templating
- Allows us to define a preset "pattern" for a webpage, that we can dynamically modify.
- For example, we could define a single "search" template that displays all the results for a given search term. We don't know twhat the term is or how many results there are ahead of time. The webpage is created on the fly.
- EJS : Embedded JavaScript (one of templating tools)
How to use EJS
- Terminal
- npm i ejs
- mkdir views
- touch views/home.ejs
- index.js
const express = require('express');
const app = express();
app.set('view engine', 'ejs');
app.listen(port, callback);
app.get(path, (req, res) => {
res.render('home');
})
- What EJS Does
- When it's tiem to render the template, EJS takes it and evaluate it in any places where it sees JS
- EJS basically runs the JS and spit out HTML
- Why use EJS
- To add logic in and interpolate data; to fill in the blank.
Setting The Views Directory
- When I'm in another directory,
- Take out current directory name where this file is located(index.js).
- Join the full path to get there, with '/views'
- Instead of the current directory where the file was executed from , the JS file uses the directory name where the 'index.js' file is located.
//index.js
const path = require('path');
app.set('views', path.join(__dirname, '/views'));
// __dirname : take out current directory name
// '/views' : join the full path to get there
EJS tags
- <%= %> : HTML escaped
- Outputs the value into the template
- Anything inside of this tag is considered as JS
- Example
//index.js
app.get('/rand', (req, res) => {
const num = Math.loor(Math.random() * 10) +1;
res.render('random', {rand: num})
})
//random.ejs
<h1> Random Number: <%= rand %> </h1>
- <% %> : Scriptlet for control flow, no output
- It allows to embed JS without the result actually being added to the template. (Embed logic into a template)
- Write JS and surround every line with <% %> tag
- Example
//random.ejs
//prints <h2> only when num is even
<% if(num%2 === 0){ %>
<h2> That is an even number! </h2>
<% } %>
Serving Static Assets in Express
- Serves CSS and JavaScript files that we want to include in the response back to the client side.
- Syntax : need a folder called 'public' and app.css file inside.
//index.js
app.use(express.static('public')); //gets executed every single request
<!-- ejs.file -->
<head>
<link rel="stylesheet" href="/app.css">
</head>
- To make 'public' folder accessable from everywhere
//index.js
app.use(express.static(path.join(__dirname, 'public')));
How to include Bootstrap
- Download 'compiled CSS and JS' file from Bootstrap website.
- Make directories: public, public/css, public/js (& include the path in index.js)
- Put bootstrap.min.css file in public/css, bootstrap.min.js file in public/js.
- Include CSS & JS files in the EJS files
- Make sure to get jQuery before <script> for js, inside of js floder.
- Example
<!--ejs-->
<link rel="stylesheet" href="/css/bootstrap.min.css">
<script src="/js/jquery.js"></script>
<script src="/js/bootstrap.min.js"></script>
Partials
- Includes
- Used by all of the templates (EJS files)
- Syntax : <%- include('path to the template') %>
- Create another ejs file that will be included by other ejs files (template for templates)
- Example
<%- include('partials/head') %>
<!-- partials: folder, head: ejs file -->
- Why use <%- %>
- If <%= %> is used, contents inside of the tag are considered as string, even if it has HTML.
RESTful Routes
Get Request
- Used to retrieve information
- Data is sent via query string
- Information is plainly visible in the URL
- Limited amount of data can be sent. (2048 characters)
Post Request
- Used to post data to the server
- Used to write/create/update
- Data is sent via request body, not a query string.
- Can send any sort of data (JSON, text, HTML, etc)
- Syntax : app.post('url ', (req, res) => { code })
req.body
- Contains key-value pairs of data submitted in the request body.
- By default, undefined
- Populated when you use body-parsing middleware such as express.json() or express.urlencoded(). (Can have multiple middlewares at once)
- Middleware : parse the req.body as this format
- It needs to be explicitly told how it should parse requrest body.
- Example : app.use(express.urlencoded({extended: true}))
REST
- REpresentational State Transfer
- A set of guidelines for how a client + server should communicate and perform CRUD operations on a given resource.
- Treating data on the server-side as resources that can be CRUDed.
- The most common way of approaching REST is in formatting the URLs and HTTP verbs in your application.
- Example: Using comments as a resource.
Name | Path | HTTP Verb | Purpose |
index | /comments | GET | Display all comments |
new | /comments/new | GET | Form to create new comment |
create | /comments | POST | Creates new comment on server |
show | /comments/:id | GET | Details for one specific comment |
edit | /comments/:id/edit | GET | Form to edit specific comment |
update | /comments/:id | PATCH | Updates specific comment on server |
destroy | /comments/:id | DELETE | Deletes specific item on server |
Index
views/comments/index.ejs : Displays all the comments here.
//index.js
app.get('/comments', (req, res) => {
res.render('comments/index', {comments})
})
New
- Creates a form so that the user can give the input.
- views/comments/new.ejs
<!-- new.ejs -->
<form action="/comment" method="POST">
<button>Submit</button>
</form>
// index.js
app.get('/comments/new', (req, res) => {
res.render('commentsnew');
})
Create
Creates new comment with the user input
// index.js
app.post('/comments', (req, res) => {
const {username, comment} = req.body;
comments.push({username, comment});
})
res.redirect([status], path)
- Use this to prevent submitting the same content repeatedly.
- By redirecting, res will include a redirect status code(302) and the path('/comments') under the location header. The browser automatically makes a request to the path. (Therefore, there are two requests being made.)
//index.js
app.post('/comments', (req, res) => {
const {username, comment} = req.body;
comments.push({username, comment});
res.redirect('/comments');
})
Show
Needs an unique identifier
//index.js
app.get('/comments/:id', (req, res) => {
const {id} = req.params;
const comment = comments.find(c => c.id === id);
res.render('comments/show', {comment});
})
UUID
- Universally Unique IDentifier
- install: npm i uuid
- require: const {v4: uuidv4} = require('uuid'); uuidv4(); //gives an unique id
Update
//index.js
app.patch( '/comments/:id' , (req, res) => {
const {id} = req.params;
const newCommentText = req.body.comment;
const foundComment = comments.find( c => c. id===id);
foundComment.comment = newCommentText;
res.redirect( '/comments' );
})
Edit
//index.js
app.get( '/comments/:id/edit' , (req, res) => {.
const {id} req.params;
const comment = comments.find( c => c.id === id);
res.render( 'comments/edit' , {comment});
})
<!-- edit.ejs -->
< form method = "POST" action = "/comments
/ <
% = comment.id% > ? _ method = PATCH" > <!-- code --> </ form >
Method Override
- Since HTML form can't have other methods than GET and POST, we use method override for other methods.
- install : npm i method-override
- Example
// Javascript
let methodOverride = require('method-override');
app.use(methodOverride('_method'));
<!-- HTML/EJS -->
<form method="POST" action="/resource?_method=DELETE">
<!-- code -->
</form>
<!-- Even though the method is POST, Express will treat it as DELETE -->
Delete
//index.js
app.delete('/comments/:id', (req, res) => {
const {id} = req.params;
comments = comments.filter(c => c.id !== id);
res.redirect('/comments');
})
<!-- show.ejs -->
<form method="POST" action="/comments/<%=comment.id%>?_method=DELETE">
<!-- code -->
</form>
* This post is a summary of Udemy Course "The Web Developer Bootcamp" by Colt Steele.
'TIL: Today I Learned' 카테고리의 다른 글
[TIL] 20201218 Middleware: The Key To Express (0) | 2020.12.19 |
---|---|
[TIL] 20201217 MongoDB / Mongoose (0) | 2020.12.17 |
[TIL] 20201215 The Terminal / Our First Brush with Node / Exploring Modules & The NPM (0) | 2020.12.15 |
[TIL] 20201214 Prototypes, Classes & OOP (0) | 2020.12.14 |
[TIL] 20201212 AJAX and API's (0) | 2020.12.13 |