Setup Node.js Express Web Server And Serve HTML Pages Without .html Extension

June 26, 2020 by Andreas Wik

node.js express web server

You can grab the final code from GitHub.

Let’s set up a Node.js Express web server and have it serve HTML pages.

Create a folder for your project, navigate to it in your terminal and run npm init -y

Next, install Express. Run npm install express.

Now that we got everything we need installed, let’s start writing code.

First we need to load Express in.

const express = require('express')

 

Next up, let’s create a new Express app and store it in a variable.

const app = express()

 

Time to tell Express what should happen when a user tries to get something from a specific URL/route. app.get() lets us set this up.

It takes two arguments. The first is a string representing the route e.g. /about. To set up the “root” route (ie mysite.com), just provide an empty string. The second argument is a callback function.  The callback function gets called with two arguments. The first one is an object with information about the request (I’ll call this req), and the second contains a bunch of functions we can use to customize what we send back (I’ll call this res).

I’ll set up 3 routes — home (empty string), about and FAQ — and in the callback function I will run res.send() to send back a tiny piece of HTML.

app.get('', (req, res) => {
    res.send('<h1>Home page</h1>')
})

app.get('/about', (req, res) => {
    res.send('<h1>About Us</h1>')
})

app.get('/faq', (req, res) => {
    res.send('<h1>Frequently Asked Questions</h1>')
})

 

Final thing before we can test it: start the server with app.listen(). It takes the port number as the first argument (I’ll use port 3000) and a callback function as the second. In the callback function I’ll just log something to the console to show that the server is running.

app.listen(3000, () => {
    console.log('Server is up and running on PORT 3000.')
})

 

So app.js now looks like this:

const express = require('express')

const app = express()

app.get('', (req, res) => {
    res.send('<h1>Home page</h1>')
})

app.get('/about', (req, res) => {
    res.send('<h1>About Us</h1>')
})

app.get('/faq', (req, res) => {
    res.send('<h1>Frequently Asked Questions</h1>')
})

app.listen(3000, () => {
    console.log('Server is up and running on PORT 3000.')
})

 

Run it with node src/app.js if you’re in the root of your project. You should see a message in the terminal saying “Server is up and running on PORT 3000.”

Open up your browser and go to localhost:3000 and you should be presented with your H1 Home page text. Then head over to localhost:3000/about and localhost:3000/faq to see the other two routes working.

 

That’s fantastic.

 

Serving HTML files

However, we want to be able to store our HTML, CSS, client side JavaScript etc in separate files. Not sending huge chunks of HTML and inline CSS/JS in res.send(). That would get messy real quick.

So let’s create a new folder called public.

In the public folder, create three HTML files: index.html, about.html and faq.html. Add some HTML in them so something shows up on the screen.

Folder structure

 

Now we need to make Express serve these files instead.

Remove all of the app.get() calls from your code so that app.js looks like this:

const express = require('express')

const app = express()

app.listen(3000, () => {
    console.log('Server is up and running on PORT 3000.')
})

 

In the top of the file we need to import the node module which we’ll make use of.

const path = require('path')

 

I want to store the path to /public in a variable, so I’ll create my new variable and store the result of path.join(), which will manipulate the path string for us. I’ll pass __dirname and the relative path to my public folder, which would be ../public.

const publicDirPath = path.join(__dirname, '../public')

 

The final thing we need to do now is to tell Express to serve up files from our public folder. We’ll do this by calling app.use(), passing in express.static() as an argument. express.static() needs the path to the public directory.

app.use(express.static(publicDirPath))

 

Now if you restart the app and go to localhost:3000 in your browser you will get the content of your index.html file. You can also request the about and FAQ pages by going to localhost:3000/about.html for example.

 

Making it work without .html extension

If you try visiting localhost:3000/about instead, you will see an error.

We can fix this using the extensions option in express.static().

app.use(express.static(publicDirPath, {extensions: ['html']}))

 

So, complete app.js:

const path = require('path')
const express = require('express')

const app = express()
const publicDirPath = path.join(__dirname, '../public')

app.use(express.static(publicDirPath, {extensions: ['html']}))

app.listen(3000, () => {
    console.log('Server is up and running on PORT 3000.')
})

 

Now if you restart the app again and go to localhost:3000/about or localhost:3000/faq you will be served the correct page.

Express server about page

 

Custom 404 Not Found page

Currently, if you go to a route that doesn’t exist, such as localhost:3000/random you will notice you get an ugly plain “Cannot /get” error.

Let’s set up a custom 404.html file to be served in these cases. In /public create your 404.html file and add some content to it.

After our call to app.use() we will make a second call to it and send back a 404 status as well as our 404.html file. Like this:

app.use(function (req, res) {
    res.status(404).sendFile(publicDirPath + '/404.html')
})

 

Final app.js:

const path = require('path')
const express = require('express')

const app = express()
const publicDirPath = path.join(__dirname, '../public')

app.use(express.static(publicDirPath, {extensions: ['html']}))

app.use(function (req, res) {
    res.status(404).sendFile(publicDirPath + '/404.html')
})

app.listen(3000, () => {
    console.log('Server is up and running on PORT 3000.')
})

 

Now if you restart the server and visit any route that doesn’t exist e.g. localhost:3000/awikio your new custom 404 Not Found file will be served.

Express 404 page

 

Well, that’s it for this time. We have only scratched the surface of what Express has to offer, but at least now we got a configured little web server up and running, handling the most basic stuff.

Life is good.

You can grab the final code from GitHub.

 

Share this article

Recommended articles

@awikio