Web Servers

What is Express?

Express is an npm module that makes it really easy to create web servers with Node.js. These servers allow you to serve up all assets to an application: HTML files, CSS for styling, client-side JS for user interaction, and more. Also, we'll be able to serve up JSON data, effectively building our own APIs.

Setting up Basic Web Server

  1. const express = require('express') imports express into file.

  2. Create a new instance of express by calling it: const app = express().

  • Note: Now all the configuration happens using properties and methods inside the app object.

  1. You now define how you want each route of your URL to behave using app.get.

  2. Inside app.get, we must first provide a route, e.g., '/about' for website.com/about or '/' for root.

  3. Then we must provide a callback: the function that gets called when user visits route. The callback receives 2 arguments:

  • req: details from the browser telling you the nature of the request

  • res: useful methods for creating a response back to the user

  1. Finally, we must start the web server using app.listen(portNum).

  • Note: You can also pass a callback that runs when the web server successfully starts.

  • Pro tip: Port 80 is the usual port for HTTP sites, while port 3000 is a conventional port for dev testing.

Here's all the steps in action:

const express = require('express')

const app = express()

app.get('/', (req, res) => {
  res.send('Hello express!')
})

app.listen(3000, () => {
  console.log('Server is up on port 3000!')
  console.log('View it at http://localhost:3000')
})

Serving up HTML and JSON

The process of serving up HTML and JSON for our routes is literally just about passing it into res.send.

res.send('<h1>I\'m an HTML tag</h1>') // HTML
res.send({ // <= JSON (converted from object)
  key: 'value',
  key2: 'value2'
})

Serving up files in a directory

Best practice is to place files that you want to serve to your user in a build folder at the root. In order to access build from the app object, you need to do the following:

  1. Use path.join to join __dirname with '../public'. This creates an absolute path to public.

  • __dirname is an absolute path to src.

  • By joining '../public' using path.join, you go up 1 directory to public.

  • Note: path.join is a cross-OS compatible way to create a path.

  1. Make app aware of public using app.use, passing the absolute path to public via express.static.

  • app.use(express.static(absPathPublic))

Pro tip: Remember how Node.js wraps our code inside a function, injecting new variables and functions? __dirname and __filename are part of this.

Dynamic Pages with Template Engine

When we use express.static, we're handing express a static directory. That means the contents of the directory never change.

Using template engines like handlebars, we can do 2 things:

  1. Render dynamic content

  2. Create reusable code that can be used across these dynamic pages, e.g. reusable header

Configuring handlebars

  1. npm install hbs. (We use hbs because it's configured to work with express.)

  2. Configure express to recognize hbs using app.set('view engine', 'hbs').

  • Note: app.set is the standard way to configure anything in express.

Bonus: You can customize the directory of your templates using...

app.set('views', path.join(__dirname, '../newDirName'))

Rendering dynamic content

Here's instructions to render dynamic content using handlebars:

  1. Create views directory at root.

  2. Create myTemplate.hbs and place HTML inside. All dynamic content is in this format: {{ varName }} (like jinja).

  • Note: You can reference assets inside public using relative paths still!

  1. Inside an app.get callback, call res.render('myTemplate', { varName: 'value' }). Now your template has access to dynamic variables!

Reusable template partials

Partials are reusable bits of HTML that you can include in your handlebars templates (e.g. headers).

  1. const hbs = require('hbs') for the module.

  2. Tell handlebars where we're going to put our partials: hbs.registerPartials(partialsPath).

  3. At partialsPath, create your partial snippet of HTML partial.hbs

  4. Inside one of your templates, you can now inject your partial via {{>partial}}.

  5. Bonus: Your partial can reference the same variables passed into your templates via res.render.

Note: If you're running nodemon, you'll need to provide an -e js,hbs flag to your command to tell nodemon to listen for hbs files as well.

404 Page

A 404 page is basically a catch-all for every URL path other than ones you explicitly created using app.get.

To do this, you need to use a wildcard in app.get like app.get('*', ...).

Note: You must place this wildcard as the last app.get call. That's because when a user visits your web server, it searches for a match to your route from top to bottom.

// 1. First checks to see if URL matches static file
app.use(express.static(publicPath))

// 2. Then checks your explicit app.get calls
app.get('/', ...)
app.get('/about', ...)

// 3. Finally matches wildcard
app.get('*', ...)

Pro tip: The wildcard character can include a specific pattern. For example, /help/* matches any routes that are subpaths of /help.

Last updated