Express.js in 60 seconds
Hello friends of the internet!
Glad you've made it! Let's get to it :)
What's Express.js (hereon referred to as "Express")?
Express is a popular backend framework for Node.js known for being minimalistic and unopinionated.
A software framework is an abstraction on the underlying language that provides a standard (hopefully easier!) way to develop applications.
Node.js is a Javascript runtime environment. It enables the execution of Javascript code outside of browsers.
Characteristics
Unopinionated
- Express offers a high degree of customization, the unopinionated nature makes it very easy to have inconsistency in the codebase; which increases cognitive load in code reviews
Flexible
- A file structure isn't imposed upon the user
Installing
Firstly, make a new directory in your projects folder
mkdir express-in-60 && cd express-in-60
Now initialize your repository using your favorite package manager (I'll use pnpm
)
pnpm init
And let's install express!
pnpm install express
When importing dependencies in files, I'm a big fan of using import ... from
statements.
To allow for that, we add the following key-value pair in our package.json
:
// package.json
{
// ...,
"type": "module"
}
This informs Node to interpret modules as ES modules and thus allow import ... from
to import them.
Set up
Now let's start the server!
Create a file called app.js
with the following contents.
// in file named: app.js (but really can be anything you want)
import express from 'express'
const app = express()
const PORT = process.env.port || 3000;
app.listen(PORT, () => {
console.log('hello wurld!')
})
express()
creates an Express Application
object that has methods for:
Routing HTTP requests; see for example, app.METHOD and app.param.
Configuring middleware; see app.route.
Rendering HTML views; see app.render.
Registering a templateengine; see app.engine.
app.listen tells the application to listen on PORT
and run the function that logs when it's ready!
Essential Functionalities
Let's go over some basic critical ideas Express to get you up and running!
Routing
Routing of static files
Route parameters
Middleware
Routing
Let's write our first route handler! In your app.js
, add the following:
// In app.js
// ...
app.get("/", (req, res) => {
res.send("GET to index!")
})
This handles GET requests to the "/" route by executing the callback function specified in the second argument.
Express supports the handling of other HTTP methods following the format of app.METHOD(path, callback)
- Where
METHOD
may be one of: get, post, put, delete, or others.
For example, to handle a POST request to the path: /organizations/google
we would write:
// In app.js
// ...
app.get("/organizations/google", (req, res) => {
res.send("GET to /organizations/google!")
})
Now let's say, the route was /organizations/netflix
- we probably don't want to create a whole new route for that!
This is where route params are helpful!
Route Params
app.get('/organizations/:org_id', (req, res) {
res.send("GET to /organizations/" + req.params.org_id)
})
Notice the
:org_id
? It designates the route segment as a "route parameter" so that we can access its value as a property onreq.params
!
Documentation: Route Parameters
Now in your browser, visit: localhost:3000/organizations/netflix
!
Static files
Serving static files, e.g. images, CSS and Javascript files is done with a built-in middleware function: express.static(root, [options])
.
Now let's create a directory in your project folder called: public
.
mkdir public
In it, create a file named: important-script.js
touch public/important-script.js
Edit your important-script.js
to have the below contents:
console.log('boo!')
Now let's go back to our app.js
. To serve files in public
directory, in our app.js
we write:
app.use(express.static("public"))
This tells the middleware to serve all files in the "public" folder, using "public" as the root and tells express to use that middleware!
Now in your browser visit localhost:3000/important-script.js
. What did you expect to happen?
Middleware
These are callback functions that have access to the request object, response object, and a next
middleware function.
You can think of them as functions that do stuff before optionally handing off to the next function. The function that follows can be another middleware function, or the request handler of a app.METHOD
call.
Note: Each request can only have one response.
Think of sending a response as "hanging up a phone call". Would it make sense to hang up on the same phone call twice in a row?
We chain middleware together, like so:
function middleware1 (request, response, next) {
// Gets called first by app.get('/dashboard')
// Checking authentication here
if (request.session.user) {
next() // allows execution of next function
} else {
// sends response for the request. no further execution happens.
return response.sendStatus(403)
}
}
function middleware2 (request, response, next) {
// Gets called second
next() // allows execution of next function
}
app.get('/dashboard', middleware1, middleware2, () => {
// Gets called last (only if .next() has been called by previous
// middleware functions!)
res.send('you\'ve reached the dashboard!')
})