Express.js in 60 seconds

Cover Image for 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:

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!")
})

Documentation: app.get

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 on req.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!')
})

References

https://dev.to/weipengjiang/expressjs-the-dangers-of-unopinionated-frameworks-and-best-practices-for-building-web-applications-3g93#