Creating a basic website with Express.js

February 09, 2018 0 Comments

Creating a basic website with Express.js

 

 


Express is described as a light-weight web framework which means we can use it to create websites. Today I am going to walk through the very basics. The website will have just few static pages which we'll be able to navigate through.

As with most frameworks nowadays, Express has its own generator. At least in the beginning it might be great to start with the generator, you'll see one way of structuring your project. It's important to keep in mind express is un-opinionated. Whilst the boilerplate is structured in a particular way, you can structure your express project which ever way makes sense to you.

In this tutorial I'll cover the very basics. By the end we'll have a website with three pages.

Lets get started.

Create your project folder. Then run the following two lines in the terminal

npm init
npm install --save express

The first line creates the package.json file, it basically initiates the project. The second installs express. Note, the --save flag simply adds express to the packages file so that if we need to reinstall the packages again, package.json knows/remembers which packages the project needs

Now create a server.js file. This is where we'll write our code.

Let's start with the very basic structure.

import express from 'express';
const app = express()
app.get('/', (req, res) => { res.send('Hello World')
})
app.listen(5656, () => { console.log('http://localhost:5656')
})

There we have created a basic website that runs at localhost port 5656.

We can give ourself the option of changing the port number from the terminal. We do this by changing the above code with something like this:

const port = process.env.PORT || 5656;
app.listen(port, () => { console.log(http://localhost:<span class="cp">${</span><span class="n">port</span><span class="cp">}</span>)
})

With that, you can run PORT=8081 npm start which changes the port number, of course, running npm run defaults to the port number being 5656

Rendering HTML in the browser.

So far our website is boring as hell. We are unable to create a website this way. Instead of sending a string of text to the browser (all though that string can be html), we would rather send html pages to the browser instead.

Express gives us the option of using template engines instead of html. This ability becomes very helpful as we start using dynamic content.

There are many template engines to choose from, my favorite is pug. Granted, it's not the most beginer friendly out of all the other options but I love it. We do not need to open and close any tags. Let's set things up so that express knows what we intend to use.

pug is a package in of itself, so first let's install that in the terminal npm --save pug. Now let's let express know that's what we are using.

app.set('view engine', 'pug');

That's it, we set the template engine to be pug. Now instead of sending Hello world to the browser. Lets render a pug page instead.

app.get('/', (req, res) => { res.render('index')
})

When setting the view engine, express expects the pug pages to be in a directory called views so let's create that directory and add the index file: views/index.pug. There we add the code we would like to display on the browser. Let's give it a pug version of hello world:

 #message h1 Hello World h3 pug's in the house

I'm sure you can guess how the above translates to html

 <div id="message"> <h1>Hello World</h1> <h3>pug's in the house</h3> </div>

And that's basically it! For a basic usage of express.

Lets create a website

To demonstrate the basic usage of express I created the following website. It's a website with few pages. Each page tells us something about the given artist. It illustrates the use of resources (images, css, js) within a react app and a more detailed use of routers.

Lets work with routing

As it can be seen from the screenshot above, this website is going to have three simple pages. This is how the routes could be created

 app.get('/charles', (req, res) => { res.render('chaplin') }) app.get('/marilyn', (req, res) => { res.render('monroe') }) app.get('/jean', (req, res) => { res.render('jimmons') })

There we have them. If users navigate to /charles a chaplin.pug template would render on the page.

In our case, the structure for each artist is going to be exactly the same, so the routers are going to render the same pug template!

 app.get('/charles', (req, res) => { res.render('index') }) app.get('/marilyn', (req, res) => { res.render('index') }) app.get('/jean', (req, res) => { res.render('index') })

Finally, with the above configuration, if users navigate to the root of the website, they'd get an error of Cannot GET / because we have removed the root router (app.get('/', (req, res) => {})). To fix this problem we can redirect users to another page we desire.

 app.get('/', (req,res) =>{ res.redirect('/charles') })

Working with dynamic data

We have the ability to pass data to the pug templates from routes. Here's an example:

 app.get('/charles', (req, res) => { res.render('index', { firstname: 'Charles', lastname: 'Chaplin', tag: 'The Little Tramp', content: '...', movies: [...] }) }) app.get('/marilyn', (req, res) => { res.render('index', { firstname: 'Marilyn', lastname: 'Monroe', tag: 'Being normal is boring', content: '...', movies: [...] }) })

We're still asking to render the index.pug page but we're also passing an object to it. Then the index.pug page would look partly something like this

 body .wrap .profile.hide a(href='#').menu span Movies .information .informationheading span.informationheadingtag= tag h1.informationname small=firstname | #{lastname} p.information__description= content 

See how the information from the json we passed in the routing is used. Pug can read all the data variables we pass by either using the equals sign if we need to render only one variable or by wrapping the variable like so my name is #{name}.

resource files

Every website needs styles and images. This is how I linked the stylesheet and the front end JavaScript.

 doctype html html head title=title link(rel='stylesheet', href='/styles/style.css') meta(name='viewport' content='windth=device-width, initial-scale=1') body .wrap ... script(src='js/script.js')

Even if the /styles/style.css and js/script.js were correctly placed in their respective directories, express would not make them available to be used as we expect with the above setup.

We first need to tell express where these files are. Or in other words, we need to tell express where our static content lives. Static content refers to anything from stylesheets, javascript files and libraries and even fonts.

To set this up, we need to write the following line in server.js:

app.use(express.static(__dirname + '/public'));

With that in place, we need to create a public directory and within it, we would create the /styles/style.css and js/script.js files. Finally, as we saw from the pug snippet above, everything in the public folder can be accessed from the root, by which I mean, public/js/script.js is available at /js/script.js.

Getting content from a json file

Whilst it's outside of the scope of this tutorial, the content for these artists would be stored in a database and would not be hardcoded inside the routes as we did above. However, for today, we can store the content in a seperate JSON file and use that in the routes. Which would help us manage the data slightly better than we are doing now.

 import data from './data/artists.json' ... app.get('/charles', (req, res) => { res.render('index', data.artist[0]) }) app.get('/marilyn', (req, res) => { res.render('index', data.artist[1]) }) app.get('/jean', (req, res) => { res.render('index', data.artist[2]) })

Now each route gets different data resulting in the following three pages:

Recap

That's it, we covered routers, templates and static files. This is the entire code we should have in server.js. Then the rest is just the usual front end code.

 import express from 'express'; import data from './data/artists.json'; const app = express(); app.set('view engine', 'pug'); app.use(express.static(__dirname + '/public')); const port = process.env.PORT || 5656; app.get('/', (req,res) =>{ res.redirect('/charles') }) app.get('/charles', (req, res) => { res.render('index', data.artist[0]) }) app.get('/marilyn', (req, res) => { res.render('index', data.artist[1]) }) app.get('/jean', (req, res) => { res.render('index', data.artist[2]) }) app.listen(port, () => { console.log(http://localhost:${port}) })

You can checkout the complete project over at github


Tag cloud