« Previous Tutorial Next tutorial »

Here we are with another episode of Five Minute React. Last time, we installed Express, our webserver. Today we’re going to take a look at the top-level files that were generated and go over what they’re doing.

First, let’s add the entire folder to Sublime and save it as a project. Click the Project menu, then click “Add Folder to Project” and choose your musiclist folder. You’ll see that the contents of the folder show up in Sublime’s sidebar, which is handy for rapidly opening different files. Click the Project menu again, choose “Save Project” and then pick a place to save your project file. I use a sublime_projects folder in my home directory.

Right. Now we have a list of files. We can forget about .gitignore and README.md for now since we created those ourselves. Let’s start with package.json – it’s simpler than app.js and we already talked about it a bit in Tutorial Five. At the top we’ve got our name and version. Then a private boolean, which is currently set to true (this isn’t really important unless we’re planning on uploading this to NPM’s database). After that we have a “scripts” section that allows us to type

yarn start

to start up our app, instead of

node ./bin/www

Finally, we have our third-party dependencies. We’re going to be adding to this list in the next tutorial, but for now it’s just the various modules that Express needs to run a basic webserver.

Now let’s take a look at a more complicated file, app.js. Go ahead and open it up. If you’ve never used Express before, this is going to seem a bit overwhelming, but remember that this is the central nervous system of your app. Considering that, it’s actually pretty short! You might also notice that it’s not using ES6 syntax – Express-Generator hasn’t quite caught up yet. We’re going to quickly convert it in a future tutorial.

OK, lines 1 through 6 are loading up various modules that the web server uses, first and foremost, Express itself.

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

If you look around, you can see these in use elsewhere in the file. For example, in line 4 we require a module called “logger” and then use it in line 19.

Lines 8 and 9 get information from a couple of route files Express generates just as a getting-started measure.

var index = require('./routes/index');
var users = require('./routes/users');

These files tell us what logic to run when a user requests a page (remember, all web server interaction is request and response!). We’ll be working with those more in a future tutorial.

Line 11 creates an instance of the Express server and assigns it to the variable “app”.

var app = express();

Lines 14 and 15 tell Express (using the app variable we just created) where to look for views, and that the views will be written in EJS.

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

That first one is a little weird, but basically what it’s doing is using a third party module to say “hey, we don’t want all of our URLs to look like musiclist.com/views/albums … we just want to use musiclist.com/albums instead, but you still need to look in /views to find the template files.”

Lines 18 through 23 are a big lump of configuration for our webserver:

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

We’ll uncomment the favicon line later, and talk about it then. Setting our logger to dev provides more robust messages to our console during development. The next three lines are used to parse incoming request bodies (ie: the stuff the browser is sending along with the request, such as JSON data or cookies). The final line is similar to our views folder above. It’s saying “serve anything in the /public folder without putting /public in front of it,” so, for example, /public/images/hi.jpg would be located at musiclist.com/images/hi.jpg

Lines 25 and 26 are important:

app.use('/', index);
app.use('/users', users);

These tell the app which route files (defined above on lines 8 and 9) to use for which URL paths. One route file can handle multiple paths, for example you could use the users route to show an index at /users and a profile at /users/starlord

This is the only section of app.js we’re likely to work with much, since we’ll be adding URLs to match the API endpoints we want to expose. If we were building a very large API, I’d probably break this out into its own file, but the MusicList API, at least in this tutorial, won’t have too many routes, so it’s fine to just keep them here.

By the way, all of these app.use lines are what’s called “middleware” which means “functionality that happens in the middle of the request” – basically things that are done before the request is delivered to your code.

Lines 29 through 33 are an example of in-line middleware, rather than middleware that’s contained in its own module.

app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

This is our 404 middleware. Note that it’s below the routes on lines 25 and 26. This is important. Those routes end the request and send a response. If the request does not match any of the routes, then it “falls through” to the next middleware function using that “next” variable, which is internally defined within the Express app. Since none of the routes succeeded, the next middleware it hits is our 404 middleware, which sets our error to, well, a 404. It then uses next() to bounce to our overall error handler, which makes up lines 36 through 44:

app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

This final bit of middleware prints the error out to the page, and can be called either at the end of the 404 to print the 404 “not found” error, or by the server when any other error happens. Note that it’ll only print the error details if our environment is set to development, which it is by default. We’ll explain changing the environment in a later tutorial.

Finally, on line 46, we export our app variable, which is our Express app, to which we’ve added all of these settings and middleware.

module.exports = app;

OK, this is getting long. Swing back next time and we’ll take a look at what’s going on in the bin, public, routes, and views folders, and how it all comes together to make a website.

« Previous Tutorial Next tutorial »