Chapter 3. Creating and setting up a MEAN project

This chapter covers

  • Managing dependencies by using npm and package.json
  • Creating and configuring Express projects
  • Setting up an MVC environment
  • Adding Twitter Bootstrap for layout
  • Publishing to a live URL, and using Git and Heroku

In this chapter, you’ll start building your application. Remember from chapters 1 and 2 that, throughout this book, you’re going to build an application called Loc8r—a location-aware web application that displays listings near users and invites people to log in and leave reviews.

Getting the source code

The source code for this application is on GitHub at https://github.com/cliveharber/gettingMean-2. Each chapter with a significant update will have its own branch. We encourage you to build it up from scratch through the course of the book, but if you want to, you can get the code that you’ll be building throughout this chapter from the chapter-03 branch on GitHub. In a fresh folder in terminal, if you already have Git installed, the following two commands will clone it:

$ git clone -b chapter-03 https://github.com/cliveharber/
gettingMean-2.git

This gives you a copy of the code that’s stored on GitHub. To run the application, you need to install some dependencies with the following commands:

$ cd gettingMean-2
$ npm install

Don’t worry if some of this doesn’t make sense yet or if some of the commands aren’t working. During this chapter, you’ll install these technologies as you go.

In the MEAN stack, Express is the Node web application framework. Together, Node.js and Express underpin the entire stack, so you’ll start there. In terms of building up the application architecture, figure 3.1 shows where this chapter focuses. You’ll do two things:

  1. Create the project and the encapsulating Express application that will house everything except the database.
  2. Set up the main Express application.
Figure 3.1. Creating the encapsulating Express application and starting to set up the main Express application

You’ll start with a bit of groundwork by looking at Express and seeing how you can manage dependencies and modules by using npm and a package.json file. You’ll need this background knowledge to get going and set up an Express project.

Before you do anything, make sure that you have everything you need installed on your machine. When that’s done, look at creating new Express projects from the command line and the various options you can specify at this point.

Express is great, but you can make it better—and get to know it better—by tinkering a little and changing some things around. This involves a quick look at model-view-controller (MVC) architecture. Here is where you get under the hood of Express a little and see what it’s doing by modifying it to have a clear MVC setup.

When the framework of Express is set up as you want it, you’ll then include Twitter’s Bootstrap framework and make the site responsive by updating the Pug templates. In the final step of this chapter, you’ll push the modified, responsive, MVC Express application to a live URL using Heroku and Git.

3.1. A brief look at Express, Node, and npm

As previously mentioned, Express is a web application framework for Node. In basic terms, an Express application is a Node application that happens to use Express as the framework. Remember from chapter 1 that npm is a package manager that gets installed when you install Node, which enables you to download Node modules or packages to extend the functionality of your application.

But how do these things work together, and how do you use them? A key piece of this puzzle is the package.json file.

3.1.1. Defining packages with package.json

In every Node application, you should have a file in the root folder of the application called package.json. This file can contain various metadata about a project, including the packages that it depends on to run. The following listing shows an example package.json file that you might find in the root of an Express project.

Listing 3.1. Example package.json file in a new Express project
{
  "name": "application-name",        1
  "version": "0.0.0",                1
  "private": true,                   1
  "scripts": {                       1
    "start": "node ./bin/www"        1
  },                                 1
  "dependencies":                   2
    "body-parser": "~1.18.3",       2
    "cookie-parser": "~1.4.3",      2
    "debug": "~4.1.0",              2
    "express": "^4.16.4",           2
    "morgan": "^1.9.1",             2
    "pug": "^2.0.3",                2
    "serve-favicon": "~2.5.0"       2
  }                                 2
}

  • 1 Various metadata defining the application
  • 2 Package dependencies needed for the application to run

This listing is the file in its entirety, so it’s not particularly complex. Various metadata at the top of the file is followed by the dependencies section. In this default installation of an Express project, quite a few dependencies are required for Express to run, but you don’t need to worry about what each one does. Express itself is modular so that you can add components or upgrade them individually.

3.1.2. Working with dependency versions in package.json

Alongside the name of each dependency is the version number that the application will use. Notice that they’re prefixed with either a tilde (~) or a caret (^).

Take a look at the dependency definition for Express 4.16.3, which specifies a particular version at three levels:

  • Major version (4)
  • Minor version (16)
  • Patch version (3)

Prefixing the whole version number with a ~ is like replacing the patch version with a wildcard, which means that the application will use the latest patch version available. Similarly, prefixing the version with a caret (^) is like replacing the minor version with a wildcard. This has become best practice, because patches and minor versions should contain only fixes that won’t have any effect on the application. But new major versions are released when a breaking change is made, so you want to avoid automatically using later versions of these in case the breaking change affects your application. If you find a module that breaks these rules, it’s easy to specify an exact version to use by removing any prefixes. Note that it’s good practice to always specify the full version and not use wildcards for this reason: you always have a reference for a specific version that you know works.

3.1.3. Installing Node dependencies with npm

Any Node application or module can have dependencies defined in a package.json file. Installing them is easy and is done the same way regardless of the application or module.

Using a terminal prompt in the same folder as the package.json file, run the following command:

$ npm install

This command tells npm to install all the dependencies listed in the package.json file. When you run it, npm downloads all the packages listed as dependencies and installs them in a specific folder in the application, called node_modules. Figure 3.2 illustrates the three key parts.

Figure 3.2. The npm modules defined in a package.json file are downloaded and installed in the application’s node_modules folder when you run the npm install terminal command.

npm installs each package into its own subfolder because each one is effectively a Node package in its own right. As such, each package also has its own package.json file defining the metadata, including the specific dependencies. It’s quite common for a package to have its own node_modules folder. You don’t need to worry about manually installing all the nested dependencies, though, because this task is handled by the original npm install command.

Adding more packages to an existing project

You’re unlikely to have the full list of dependencies for a project right from the outset. It’s far more likely that you’ll start with a few key ones that you know you’ll need and perhaps some that you always use in your workflow.

Using npm, it’s easy to add more packages to the application whenever you want. Find the name of the package you want to install, open a command prompt in the same folder as the package.json file, and then run a simple command like this:

$ npm install --save package-name

With this command, npm downloads and installs the new package in the node_modules folder. The --save flag tells npm to add this package to the list of dependencies in the package.json file. As of npm version 5, the --save flag is no longer required, as NPM saves changes to the package.json file automatically. We’ve added it here for completeness. When this command is run, npm generates a package-lock.json file to maintain versions of dependencies between environments, which is helpful when you’re deploying from development to a live server.

Updating packages to later versions

The only time npm downloads and reinstalls existing packages is when you upgrade to a new version. When you run npm install, npm goes through all the dependencies and checks the following:

  • The version defined in the package-lock.json file (if it exists) or package.json (if it doesn’t)
  • The latest matching version on npm (which may be different if you used ~ or ^)
  • The version of the module (if there is one) in the node_modules folder

If your installed version is different from the definition in the package.json (or package-lock.json) file, npm downloads and installs the defined version. Similarly, if you’re using a wildcard, and a later matching version is available, npm downloads and installs it in place of the previous version.

With that knowledge under your belt, you can start creating your first Express project.

3.2. Creating an Express project

All journeys must have a starting point, which for building a MEAN application is creating a new Express project. To create an Express project, you’ll need to have five key things installed on your development machine:

  • Node and npm
  • The Express generator installed globally
  • Git
  • Heroku
  • Suitable command-line interface (CLI) or terminal

3.2.1. Installing the pieces

If you don’t have Node, npm, or the Express generator installed yet, see appendix A for instructions and pointers to online resources. All can be installed on Windows, macOS, and all mainstream Linux distributions.

By the end of this chapter, you’ll also have used Git to manage the source control of your Loc8r application and pushed it to a live URL hosted by Heroku. Please take a look through appendix B, which guides you through setting up Git and Heroku.

Depending on your operating system, you may need to install a new CLI or terminal. See appendix B to find out whether this requirement applies to you.

Note

Throughout this book, we’ll often refer to the CLI as terminal. When we say “Run this command in terminal,” we mean run it in whichever CLI you’re using. When terminal commands are included as code snippets throughout this book, they start with a $. You shouldn’t type this symbol in terminal; it’s simply there to denote a command-line statement. If you’re entering the echo command $ echo 'Welcome to Getting MEAN', for example, type echo 'Welcome to Getting MEAN'.

3.2.2. Verifying the installations

To create a new Express project, you must have Node and npm installed, and you must also have the Express generator installed globally. You can verify by checking for the version numbers in terminal, using the following commands:

$ node --version
$ npm --version
$ express --version

Each of these commands should output a version number to terminal. If one of them fails, head to appendix A for details on how to install it again.

3.2.3. Creating a project folder

Assuming that all is good, start by creating a new folder on your machine called loc8r. This folder can be on your desktop, in your documents, or in a Dropbox folder; the location doesn’t matter as long as you have full read and write access rights to the folder.

Simon personally does a lot of his MEAN development in Dropbox folders so that his work is immediately backed up and accessible on any of his machines. If you’re in a corporate environment, however, this approach may not be suitable for you, so create the folder wherever you think is best.

3.2.4. Configuring an Express installation

An Express project is installed from the command line, and the configuration is passed in with parameters of the command you use. If you’re not familiar with using the command line, don’t worry; none of what we’ll go through in the book is particularly complex, and it’s all easy to remember. Once you’ve started using it, you’ll probably love how it makes some operations so fast.

You can install Express in a folder with a simple command (but don’t do this yet):

$ express

This command installs the framework with default settings in your current folder. This step probably is a good start, but take a look at some configuration options first.

Configuration options when creating an Express project

What can you configure when creating an Express project this way? You can specify the following:

  • Which HTML template engine to use
  • Which CSS preprocessor to use
  • Whether to create a .gitignore file

A default installation uses the Jade template engine, but it has no CSS preprocessing or session support. You can specify a few options, as laid out in table 3.1.

Table 3.1. Command-line configuration options for creating a new Express project

Configuration command

Effect

--css=less|stylus Adds a CSS preprocessor to your project, either Less or Stylus, depending on which you type in the command
--view=ejs|hbs|pug Changes the HTML template engine from Jade to EJS, Handlebars, or Pug, depending on which you type
--git Adds a .gitignore file to the directory

You aren’t going to do that here, but if you want to create a project that uses the Less CSS preprocessor and the Handlebars template engine and includes a .gitignore file, you’d run the following command in terminal:

$ express --css=less --view=hbs --git

To keep things simple in your project, you won’t use CSS preprocessing, so you can stick with the default of plain CSS. But you do need to use a template engine, so in the next section, you’ll take a quick look at the options.

Different template engines

When you’re using Express in this way, a few template options are available, including Jade, EJS, Handlebars, and Pug. The basic workflow of a template engine is creating the HTML template, including placeholders for data, and then passing it some data. Then the engine compiles the template and data together to create the final HTML markup that the browser will receive.

All engines have their own merits and quirks, and if you already have a preferred one, that’s fine. In this book, you’ll use Pug. Pug is powerful and provides all the functionality you’re going to need. Pug is the next evolution of Jade; due to trademark issues, the creators of Jade had to rename it, and they chose Pug. Jade still exists, so existing projects won’t break, but all new releases are under the name Pug. Jade was (and still is) the default template engine in Express, so you’ll find that most examples and projects online use it, which means that it’s helpful to be familiar with the syntax. Finally, the minimal style of Jade and Pug make them ideal for code samples in a book.

A quick look at Pug

Pug is unusual compared with the other template engines, in that it doesn’t contain HTML tags in the templates. Instead, Pug takes a rather minimalist approach, using tag names, indentation, and a CSS-inspired reference method to define the structure of the HTML. The exception is the <div> tag. Because it’s so common, if the tag name is omitted from the template, Pug assumes that you want a <div>.

Tip

Pug templates must be indented with spaces, not tabs.

The following code snippet shows a simple example of a Pug template:

#banner.page-header               1
  h1 My page                      1
  p.lead Welcome to my page       1

  • 1 Pug template contains no HTML tags

This snippet shows the compiled output:

<div id="banner" class="page-header">        1
  <h1>My page</h1>                           1
  <p class="lead">Welcome to my page</p>     1
</div>                                       1

  • 1 Compiled output is recognizable HTML

From the first lines of the input and output, you should be able to see that

  • With no tag name specified, a <div> is created.
  • #banner in Pug becomes id="banner" in HTML.
  • .page-header in Pug becomes class="page-header" in HTML.

Note also that the indentation in Pug is important, as it defines the nesting of the HTML output. Remember that the indentation must be done with spaces, not tabs!

To recap, you don’t need a CSS preprocessor, but you do want the Pug template engine. How about the .gitignore file?

A quick intro to .gitignore files

A .gitignore file is a simple configuration file that sits in the root of your project folder. This file specifies which files and folders Git commands should ignore. In essence, it says, “Pretend these files don’t exist, and don’t track them,” meaning that they won’t end up in source control.

Common examples include log files and the node_modules folder. Log files don’t need to be up on GitHub for everyone to see, and your Node dependencies should be installed from npm whenever your application is downloaded. You’ll be using Git in section 3.5, so ask the Express generator to create a file for you.

With that starting knowledge behind you, it’s time to create a project.

3.2.5. Creating an Express project and trying it out

You know the basic command for creating an Express project and have decided to use the Pug template engine. You’ll also let it generate a .gitignore file for you. Now create a new project. In section 3.2.3, you should have created a new folder called loc8r. Navigate to this folder in terminal, and run the following command:

$ express --view=pug --git

This command creates a bunch of folders and files inside the loc8r folder that form the basis of your Loc8r application. But you’re not quite ready yet. Next, you need to install the dependencies. As you may remember, you do this by running the following command from a terminal prompt in the same folder as the package.json file:

$ npm install

As soon as you run it, your terminal window lights up with all the things it’s downloading. When it finishes, the application is ready for a test drive.

Trying it out

Make sure that everything works as expected. In section 3.2.6, we’ll show you a better way of running the project.

In terminal, in the loc8r folder, run the following command (but if your application is in a folder with a different name, swap out loc8r accordingly):

$ DEBUG=loc8r:* npm start

You should see a confirmation similar to this:

loc8r:server Listening on port 3000 +0ms

This confirmation means that the Express application is running. You can see it in action by opening a browser and heading over to localhost:3000. We hope that you’ll see something like the screenshot in figure 3.3.

Figure 3.3. Landing page for a bare-bones Express project

Admittedly, this isn’t exactly ground-breaking stuff, but getting the Express application up and running to the point of working in a browser was easy, right?

If you head back to terminal now, you should see a couple of log statements confirming that the page has been requested and that a stylesheet has been requested. To get to know Express a little better, take a look at what’s going on here.

How Express handles the requests

The default Express landing page is simple. The page contains a small amount of HTML, of which some of the text content is pushed as data by the Express route. There’s also a CSS file. The logs in terminal should confirm that this is what Express requested and has returned to the browser. But how?

About Express middleware

The app.js file contains a bunch of lines that start with app.use somewhere in the middle. These lines are known as middleware. When a request comes in to the application, it passes through each piece of middleware in turn. Each piece of middleware may or may not do something with the request, but it’s always passed on to the next one until it reaches the application logic itself, which returns a response.

Take app.use(express.cookieParser());, for example. This line takes an incoming request, parses out any of the cookie information, and attaches the data to the request in a way that makes it easy to reference in the controller code.

You don’t need to know what each piece of middleware does right now, but you may well find yourself adding to this list as you build out applications.

All requests to the Express server run through the middleware defined in the app.js file (see the sidebar “About Express middleware”). As well as doing other things, a default piece of middleware looks for paths to static files. When the middleware matches the path against a file, Express returns this asynchronously, ensuring that the Node.js process isn’t tied up with this operation and therefore blocking other operations. When a request runs through all the middleware, Express attempts to match the path of the request against a defined route. We’ll get into this topic in a bit more detail in section 3.3.3.

Figure 3.4 illustrates this flow, using the example of the default Express homepage from figure 3.3. The flow in figure 3.4 shows the separate requests made and how Express handles them differently. Both requests run through the middleware as a first action, but the outcomes are different.

Figure 3.4. The key interactions and processes that Express goes through when responding to the request for the default landing page. The HTML page is processed by Node to compile data and a view template, and the CSS file is served asynchronously from a static folder.

3.2.6. Restarting the application

A Node application compiles before running, so if you make changes to the application code while it’s running, they won’t be picked up until the Node process is stopped and restarted. Note that this is true only for application code; Jade templates, CSS files, and client-side JavaScript can all be updated on the fly.

Restarting the Node process is a two-step procedure. First, you have to stop the running process in terminal by pressing Ctrl-C. Then, you have to start the process again in terminal, using the same command as before: DEBUG=loc8r:* npm start.

This process doesn’t sound problematic, but when you’re actively developing and testing an application, having to do these two steps every time you want to check an update becomes quite frustrating. Fortunately, there’s a better way.

Automatically restarting the application with nodemon

Some services have been developed to monitor application code and restart the process when they detect that changes have been made. One such service, and the one you’ll use in this book, is nodemon. nodemon wraps the Node application and, other than monitoring for changes, causes no interference.

To use nodemon, start by installing it globally, much as you did with Express. Use npm in terminal:

$ npm install -g nodemon

When the installation is finished, you’ll be able to use nodemon wherever you want. Using it is simple. Instead of typing node to start the application, you type nodemon. So, making sure that you’re in the loc8r folder in terminal and that you’ve stopped the Node process, if it’s still running, enter the following command:

$ nodemon

You should see a few extra lines output to terminal, confirming that nodemon is running and that it has started node ./bin/www. If you head back over to your browser and refresh, you should see that the application is still there.

Note

nodemon is intended only for easing the development process in your development environment and shouldn’t be used in a live production environment. Projects like pm2 or foreman are designed for production use.

Using the supplied Docker environment

Each chapter comes with a Dockerfile set up. Head over to appendix B to see how to install and use the Docker containers. You don’t have to use Docker to benefit from this book; it’s been added as a convenience.

3.3. Modifying Express for MVC

Firstly, what is MVC architecture? MVC architecture separates the data (model), the display (view) and the application logic (controller). This separation aims to remove any tight coupling between the components, theoretically making code more maintainable and reusable. A bonus is that these components fit nicely into your rapid prototype development approach and allow you to concentrate on one aspect at a time as we discuss each part of the MEAN stack.

Whole books are dedicated to the nuances of MVC, but we won’t go to that depth here. We’ll keep the discussion of MVC at a high level and show you how to use it with Express to build your Loc8r application.

3.3.1. A bird’s-eye view of MVC

Most applications or sites that you build are designed to take an incoming request, do something with it, and return a response. At a simple level, this loop in an MVC architecture works like this:

  1. A request comes into the application.
  2. The request gets routed to a controller.
  3. The controller, if necessary, makes a request to the model.
  4. The model responds to the controller.
  5. The controller merges the view and the data to form a response.
  6. The controller sends the generated response to the original requester.

In reality, depending on your setup, the controller may compile the view before sending the response to the visitor. The effect is the same, though, so keep this simple flow in mind as a visual for what will happen in your Loc8r application. See figure 3.5 for an illustration of this loop.

Figure 3.5. Request-response flow of a basic MVC architecture

Figure 3.5 highlights the parts of the MVC architecture and shows how they link together. It also illustrates the need for a routing mechanism along with the model, view, and controller components.

Now that you’ve seen how you want the basic flow of your Loc8r application to work, it’s time to modify the Express setup to make this happen.

3.3.2. Changing the folder structure

If you look inside the newly created Express project in the loc8r folder, you should see a file structure including a views folder and even a routes folder, but no mention of models or controllers. Rather than cluttering the root level of the application with some new folders, keep things tidy by creating one new folder for all your MVC architecture. Follow these three quick steps:

  1. Create a new folder called app_server.
  2. In app_server, create two new folders called models and controllers.
  3. Move the views and routes folders from the root of the application into the app_server folder.

Figure 3.6 illustrates these changes and shows the folder structures before and after modification.

Figure 3.6. Changing the folder structure of an Express project into an MVC architecture

Now you have an obvious MVC setup in the application, which makes it easier to separate your concerns. But if you try to run the application now, it won’t work, as you’ve just broken it. So fix it. Express doesn’t know that you’ve added some new folders or have any idea what you want to use them for, so you need to tell it.

3.3.3. Using the views and routes relocated folders

The first thing you need to do is tell Express that you’ve moved the views and routes folders, because Express will be looking for them in their old location.

Using the new views folder location

Express will be looking for /views, but it needs to look for /app_server/views. Changing the path is simple. In app.js, find the following line:

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

Change it to the following (modifications in bold):

app.set('views', path.join(__dirname, 'app_server', 'views'));

Your application still won’t work, because you’ve moved the routes, so tell Express about them too.

Using the new routes folder location

Express will be looking for /routes, but it needs to look for /app_server/routes. Changing this path is also simple. In app.js, find the following lines:

const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');

Change these lines to the following (modifications in bold):

const indexRouter = require('./app_server/routes/index');
const usersRouter = require('./app_server/routes/users');
Defining variables in ES2015

One of the most fundamental changes in ES2015 is deprecation of the var keyword to define variables. It still works, but instead, you should use one of the two new keywords: const and let. Variables defined with const can’t be changed at a later point in the code, whereas variables defined with let can be changed.

Best practice is to define variables with const unless their values are going to change. All instances of var in app.js can be changed to const. We’ve done this in the source code for this book; feel free to do it too.

One other thing to bear in mind is that const and let are block-level variable initializers, whereas var is a context-level variable initializer. If these terms mean nothing to you, read appendix D, available with the e-book or online from manning.com.

Note that you also changed var to const to upgrade to ES2015. Check out the sidebar “Defining variables in ES2015” if this concept is new to you. If you save your changes and run the application again, you’ll find that it works once more!

3.3.4. Splitting controllers from routes

In a default Express setup, controllers are part of the routes, but you want to separate them out. Controllers should manage the application logic, and routing should map URL requests to controllers.

Understanding route definition

To understand how routes work, take a look at the route already set up for delivering the default Express homepage. Inside index.js in app_server/routes, you should see the following code snippet:

/* GET homepage. */
router.get('/', function(req, res) {               1
  res.render('index', { title: 'Express' });       2
});

  • 1 Where the router looks for the URL
  • 2 Controller content, albeit very basic right now

In the code at 1 you can see router.get('/'. The router checks internally for GET requests that map to the homepage URL path, which is '/'. The anonymous function that runs the code 1 is the controller. This basic example has no application code to speak of. So 1 and 2 are the pieces you want to separate here.

Rather than dive straight in and put the controller code in the controllers folder, test the approach in the same file first. To do this, you can define the anonymous function from the route definition as a named function. Then pass the name of this function through as the callback in the route definition. Both of these steps are in the following listing, which you can put in place inside app_server/routes/index.js.

Listing 3.2. Taking the controller code out of the route: step 1
const homepageController = (req, res) => {      1
  res.render('index', { title: 'Express' });    1
};                                              1
/* GET homepage. */
router.get('/', homepageController);            2

  • 1 Gives a name to the arrow function
  • 2 Passes the name of the function through as a callback in the route definition

If you refresh your homepage now, it should still work as before. You haven’t changed anything in how the site works—only moved a step toward separating concerns.

Understanding res.render

You’ll look at this topic more in chapter 4, but render is the Express function for compiling a view template to send as the HTML response that the browser will receive. The render method takes the name of the view template and a JavaScript data object in the following construct:

Note that the template file doesn’t need to have the file extension suffix, so index.pug can be referenced as index. You also don’t need to specify the path to the view folder, because you’ve already done this in the main Express setup.

Now that you’re clear about how route definition works, it’s time to put the controller code in its proper place.

Moving the controller out of the routes file

In Node, to reference code in an external file, you create a module in your new file, and then require it in the original file. See the sidebar “Creating and using Node modules” for some overarching principles behind this process.

Creating and using Node modules

Taking some code out of a Node file to create an external module is, fortunately, simple. In essence, you create a new file for your code, choose which bits of it you want to expose to the original file, and then require your new file in your original file.

In your new module file, you expose the parts of the code that you want to by using the module.exports method, like so:

module.exports = function () {
  console.log("This is exposed to the requester");
};

Then you require this in your main file, like so:

require('./yourModule');

If you want your module to have separate named methods exposed, you can do so by defining them in your new file in the following way:

module.exports.logThis = function (message){
  console.log(message);
};

Even better is to define a named function and export it at the end of the file. This lets you expose all the functions you need to in one place, creating a handy list for your future self (or subsequent developers).

const logThis = function (message) {
  console.log(message);
};
module.exports = {
 logThis
};

To reference this in your original file, you need to assign your module to a variable name, and then invoke the method. You might enter this in your main file:

const yourModule = require('./yourModule');
yourModule.logThis("Hooray, it works!");

This code assigns your new module to the variable yourModule. The exported function logThis is now available as a method of yourModule.

Note that, when using the require function, you don’t need to specify a file extension. The require function looks for a couple of things: an npm module, a JavaScript file of the same name, or an index.js file inside a folder of the given name.

The first thing you need to do is create a file to hold the controller code. Create a new file called main.js in app_server/controllers. In this file, create and export a method called index, and use it to house the res.render code, as shown in the following listing.

Listing 3.3. Setting up the homepage controller in app_server/controllers/main.js
/* GET homepage */
const index = (req, res) => {                    1
  res.render('index', { title: 'Express' });     2
};
module.exports = {                               3
 index                                           3
};                                               3

  • 1 Creates an index function
  • 2 Includes controller code for the homepage
  • 3 Exposes the index function as a method

That’s all there is to exporting the controller. The next step is to require this controller module in the routes file so that you can use the exposed method in the route definition. The following listing shows how the index.js file in app_server/routes should look.

Listing 3.4. Updating the routes file to use external controllers
const express = require('express');
const router = express.Router();
const ctrlMain = require('../controllers/main');    1
/* GET homepage. */
router.get('/', ctrlMain.index);                    2
module.exports = router;

  • 1 Requires the main controllers file
  • 2 References the index method of the controllers in the route definition

This code links the route to the new controller by “requiring” the controller file 1 and referencing the controller function in the second parameter of the router.get function 2.

Now you have the routing and controller architecture, as illustrated in figure 3.7, where app.js requires routes/index.js, which in turn requires controllers/main.js. If you test this now in your browser, you should see that the default Express homepage displays correctly once again.

Figure 3.7. Separating the controller logic from the route definitions

Everything is set up with Express for now, so it’s almost time to start the building process. But you need to do a couple more things. The first is adding Twitter Bootstrap to the application.

3.4. Importing Bootstrap for quick, responsive layouts

As discussed in chapter 1, your Loc8r application uses Twitter’s Bootstrap framework to speed the development of a responsive design. You’ll also make the application stand out by adding some font icons and custom styles. The aim is to help you keep moving forward quickly with building the application and not get sidetracked with the semantics of developing a responsive interface.

3.4.1. Downloading Bootstrap and adding it to the application

Instructions for downloading Bootstrap, downloading the font icons (by Font Awesome), creating a custom style, and adding the files to the project folder are in appendix B. Note that you use Bootstrap 4.1. A key point is that the downloaded files are all static files to be sent directly to the browser; they don’t need any processing by the Node engine. Your Express application already has a folder for this purpose: the public folder. When you have it ready, the public folder should look something like figure 3.8.

Figure 3.8. Structure of the public folder in the Express application after adding Bootstrap

Bootstrap also requires jQuery and Popper.js for some of the interactive components to work. Because they aren’t core to your application, you’ll reference them from a content delivery network (CDN) in the next step.

3.4.2. Using Bootstrap in the application

Now that all of the Bootstrap pieces are sitting in the application, it’s time to hook it up to the front end, which means taking a look at the Pug templates.

Working with Pug templates

Pug templates often have a main layout file that has defined areas for other Pug files to extend. This makes a great deal of sense when you’re building a web application, because many screens or pages have the same underlying structure with different content on top.

This is how Pug appears in a default Express installation: If you look in the views folder in the application, you see three files—layout.pug, index.pug, and error.pug. The index.pug file is controlling the content for the index page of the application. Open it, and you see that not much is in there. The entire contents are shown in the following listing.

Listing 3.5. The complete index.pug file
extends layout                  1
block content                   2
  h1= title                     3
  p Welcome to #{title.}        3

  • 1 Declares that this file is extending the layout file
  • 2 Declares that the following section goes into an area of the layout file called content
  • 3 Outputs h1 and p tags to the content area

There’s more going on here than meets the eye. Right at the top of the file is a statement declaring that this file is an extension of another file 1—in this case, the layout file. Following is a statement defining a block of code 2 that belongs to a specific area of the layout file: an area called content. Finally, there’s the minimal content displayed on the Express index page: a single <h1> tag and a single <p> tag 3.

There are no references to <head> or <body> tags here, or any stylesheet references. These are handled in the layout file, so that’s where you want to go to add global scripts and stylesheets to the application. Open layout.pug, and you should see something similar to the following listing.

Listing 3.6. Default layout.pug file
doctype html
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    block content                       1

  • 1 Empty named block can be used by other templates

This shows the layout file being used for the basic index page in the default Express installation. There’s a head section and a body section, and within the body section, there’s a block content line with nothing inside it. This named block can be referenced by other Pug templates, such as the index.pug file in listing 3.5. The block content from the index file gets pushed into the block content area of the layout file when the views are compiled.

Adding Bootstrap to the entire application

If you want to add some external reference files to the entire application, using the layout file makes sense in the current setup. In layout.pug, you need to accomplish four things:

  • Reference the Bootstrap and Font Awesome CSS files.
  • Reference the Bootstrap JavaScript file.
  • Reference jQuery and Popper.js, which Bootstrap requires.
  • Add viewport metadata so that the page scales nicely on mobile devices.

The CSS file and the viewport metadata should both be in the head of the document, and the two script files should be at the end of the body section. The following listing shows all this in place in layout.pug, with the new lines in bold.

Listing 3.7. Updated layout.pug including Bootstrap references
doctype html
html
  head
    meta(name='viewport', content='width=device-width,
      initial-scale=1.0')                                               1
    title= title
    link(rel='stylesheet',  href='/stylesheets/bootstrap.min.css')        2
    link(rel='stylesheet', href='/stylesheets/all.min.css')               2
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    block content
    script(src='https://code.jquery.com/jquery-3.3.1.slim.min.js',        3
    integrity='sha384-                                                  3
    q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo',  3
    crossorigin='anonymous')                                            3
    script(src='https://cdnjs.cloudflare.com/ajax/libs/                   3
    popper.js/1.14.3/umd/popper.min.js',integrity='sha384-              3
    ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49',  3
    crossorigin='anonymous')                                              3
    script(src='/javascripts/bootstrap.min.js')                           4

  • 1 Sets the viewport metadata for better display on mobile devices
  • 2 Includes Bootstrap and Font Awesome CSS
  • 3 Brings in jQuery and Popper, needed by Bootstrap. Make sure that the script tags are all at the same indentation.
  • 4 Brings in the Bootstrap JavaScript file

With that done, any new template that you create automatically has Bootstrap included and will scale on mobile devices—as long as your new templates extend the layout template, of course. Should you have any problems or unexpected results at this stage, remember that Pug is sensitive to indentation, spacing, and newlines. All indentation must be done with spaces to get the correct nesting in the HTML output.

Tip

If you followed along in appendix B, you’ll also have some custom styles in the style.css file in /public/stylesheets to prevent the default Express styles from overriding the Bootstrap files and help you get the look you want.

Now you’re ready to test.

Verifying that it works

If the application isn’t already running with nodemon, start it, and view it in your browser. The content hasn’t changed, but the appearance should have. You should have something that looks like figure 3.9.

Figure 3.9. Bootstrap and your styles having an effect on the default Express index page

If yours doesn’t look like this, make sure that you’ve added the custom styles as outlined in appendix B. Remember that you can get the source code of the application so far from the chapter-03 branch on GitHub. In a fresh folder in terminal, use the following command to clone it:

$ git clone -b chapter-03 https://github.com/cliveharber/
    gettingMean-2.git

Now you’ve got something working locally. In the next section, you’ll see how you can get it running on a live production server.

3.5. Making it live on Heroku

A common perceived headache with Node applications is deploying them to a live production server. You’re going to get rid of that headache early and push your Loc8r application to a live URL right away. As you iterate and build it up, you can keep pushing out the updates. For prototyping, this approach is great, because it makes showing your progress to others easy.

As mentioned in chapter 1, there are a few PaaS providers such as Google Cloud Platform, Nodejitsu, OpenShift, and Heroku. You’ll use Heroku here, but there’s nothing to stop you from trying other options. Next, you’ll get Heroku up and running, and walk through a few basic Git commands to deploy your application to a live server.

3.5.1. Getting Heroku set up

Before you can use Heroku, you need to sign up for a free account and install the Heroku CLI on your development machine. Appendix B has more detailed information on how to do this. You also need a bash-compatible terminal; the default terminal for Mac users is fine, but the default CLI for Windows users won’t do. If you’re on Windows, you need to download something like the GitHub terminal, which comes as part of the GitHub desktop application. When you have everything set up, you can continue getting the application ready to push live.

Updating package.json

Heroku can run applications on various types of codebases, so you need to tell it what your application is running. Besides telling it that you’re running a Node application using npm as the package manager, you also need to tell it which version you’re running to ensure that the production setup is the same as the development setup.

If you’re not sure which versions of Node and npm you’re running, you can find out with a couple of terminal commands:

$ node --version
$ npm --version

Currently, these commands return v11.0.0 and 6.4.1, respectively. Using the ~ syntax to add a wildcard for a minor version, as you’ve seen previously, you need to add these to a new engines section in the package.json file. The complete updated package.json file is shown in the following listing, with the added section in bold.

Listing 3.8. Adding an engines section to package.json
{
  "name": "Loc8r",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "engines": {                    1
    "node": ">=11.0.0",           1
    "npm": ">=6.4.0"              1
  },                              1
  "dependencies": {
    "body-parser": "~1.18.3",
    "cookie-parser": "~1.4.3",
    "debug": "~3.1.0",
    "express": "~4.16.3",
    "morgan": "~1.9.0",
    "pug": "~2.0.0-beta11",
    "serve-favicon": "~2.5.0"
  }
}

  • 1 Adds an engines section to package.json to tell Heroku which platform your application is on and which version to use

When pushed up to Heroku, this code tells Heroku that your application uses the latest minor version of Node 11 and the latest minor version of npm 6.

Creating a Procfile

The package.json file tells Heroku that the application is a Node application but doesn’t tell it how to start it. For this task, you need a Procfile, which is used to declare the process types used by your application and the commands used to start them.

For Loc8r, you want a web process, and you want it to run the Node application. In the root folder of the application, create a file called Procfile. (The name is case sensitive and has no file extension.) Enter the following line in the Procfile:

web: npm start

When pushed up to Heroku, this file tells Heroku that the application needs a web process and that it should run npm start.

Testing it locally with Heroku Local

The Heroku CLI comes with a utility called Heroku Local. You can use this utility to verify your setup and run your application locally before pushing the application up to Heroku. If the application is currently running, stop it by pressing Ctrl-C in the terminal window that’s running the process. Then, in the terminal window, make sure you’re in your application folder, and enter the following command:

$ heroku local

If all is well with the setup, this command starts the application running on localhost again, but this time on a different port: 5000. The confirmation you get in terminal should be along these lines:

16:09:02 web.1 | > [email protected] start /path/to/your/application/folder
16:09:02 web.1 | > node ./bin/www

You’ll probably also see the warning No ENV file found. This message is nothing to worry about at this stage. If you fire up a browser and head over to localhost:5000 (note that the port is 5000 instead of 3000), you should see the application up and running again.

Now that you know the setup is working, it’s time to push your application up to Heroku.

3.5.2. Pushing the site live using Git

Heroku uses Git as the deployment method. If you already use Git, you’ll love this approach; if you haven’t, you may feel a bit apprehensive about it, because the world of Git can be complex. But it doesn’t need to be, and when you get going, you’ll love this approach too!

Storing the application in Git

The first action is storing the application in Git on your local machine. This process involves the following three steps:

  1. Initialize the application folder as a Git repository.
  2. Tell Git which files you want to add to the repository.
  3. Commit these changes to the repository.

This process may sound complex but isn’t. You need a single, short terminal command for each step. If the application is running locally, stop it in terminal (Ctrl-C). Then, ensuring you’re still in the root folder of the application, stay in terminal, and run the following commands:

$ git init                         1
$ git add --all                    2
$ git commit -m "First commit"     3

  • 1 Initializes folder as a local Git repository
  • 2 Adds everything in folder to the repository
  • 3 Commits changes to the repository with a message

These three things together create a local Git repository containing the entire codebase for the application. When you update the application later and want to push some changes live, you’ll use the second two commands, with a different message, to update the repository. Your local repository is ready. It’s time to create the Heroku application.

Creating the Heroku application

This next step creates an application on Heroku as a remote Git repository of your local repository. You do all this with a single terminal command:

$ heroku create

You’ll see a confirmation in terminal of the URL that the application is on, the Git repository address, and the name of the remote repository, as in this example:

https://pure-temple-67771.herokuapp.com/ | [email protected]:pure-temple-
     67771.git
Git remote heroku added

If you log in to your Heroku account in a browser, you’ll also see that the application exists there. Now that you have a place on Heroku for the application, the next step is pushing the application code up.

Deploying the application to Heroku

You have the application stored in a local Git repository, and you’ve created a new remote repository on Heroku. The remote repository is empty, so you need to push the contents of your local repository to the heroku remote repository.

If you don’t know Git, there’s a single command for this purpose, which has the following construct:

This command pushes the contents of your local Git repository to the heroku remote repository. Currently, you only have a single branch in your repository—the master branch—so that’s what you’ll push to Heroku. See the sidebar “What are Git branches?” for more information on Git branches.

When you run this command, terminal displays a load of log messages as it goes through the process, eventually showing (about five lines from the end) a confirmation that the application has been deployed to Heroku. This confirmation is something like the following except that, of course, you’ll have a different URL:

http://pure-temple-67771.herokuapp.com deployed to Heroku
What are Git branches?

If you work on the same version of the code and push it up to a remote repository like Heroku or GitHub periodically, you’re working on the master branch. This process is absolutely fine for linear development with one developer. If you have multiple developers, however, or your application is already published, you don’t want to be doing your development on the master branch. Instead, you start a new branch from the master code in which you can continue development, add fixes, or build a new feature. When work on a branch is complete, it can be merged back into the master branch.

About web dynos on Heroku

Heroku uses the concept of dynos for running and scaling an application. The more dynos you have, the more system resources and processes you have available to your application. Adding more dynos when your application gets bigger and more popular is easy.

Heroku also has a great free tier, which is perfect for application prototyping and building a proof of concept. You get one web dyno free with each application, which is more than adequate for your purposes here. If you have an application that needs more resources, you can always log in to your account and pay for more.

In the following section, you’ll check out the live URL.

Viewing the application on a live URL

Everything is in place, and the application is live on the internet! You can see it by typing the URL given to you in the confirmation, via your account on the Heroku website, or by using the following terminal command:

$ heroku open

This command launches the application in your default browser, and you should see something like figure 3.10.

Figure 3.10. MVC Express application running on a live URL

Your URL will be different, of course, and within Heroku, you can change it to use your domain name instead of the address it gave you. In the application settings on the Heroku website, you can change it to the more meaningful subdomain herokuapp.com.

Having your prototype on an accessible URL is handy for cross-browser and cross-device testing, as well as for sending it to colleagues and partners.

A simple update process

Now that the Heroku application is set up, updating it is easy. Every time you want to push some new changes through, you need three terminal commands:

$ git add --all                            1
$ git commit -m "Commit message here"      2
$ git push heroku master                   3

  • 1 Adds all changes to the local Git repository
  • 2 Commits changes to the local repository with a useful message
  • 3 Pushes changes to the Heroku repository

That’s all there is to it, for now at least. Things may get a bit more complex if you have multiple developers and branches to deal with, but the process of pushing the code to Heroku using Git remains the same.

In chapter 4, you’ll get to know Express even more when you build out a prototype of the Loc8r application.

Summary

In this chapter, you learned

  • How to create a new Express application
  • How to manage application dependencies with npm and the package.json file
  • How a standard Express project can be changed to meet an MVC approach to architecture
  • How routes and controllers fit together
  • The simplest way to publish an Express application live to Heroku using Git
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.23.101.60