diff --git a/chapter2/chapter2.md b/chapter2/chapter2.md index e86c26cc..676fc5ba 100755 --- a/chapter2/chapter2.md +++ b/chapter2/chapter2.md @@ -279,18 +279,18 @@ So far, we've covered Express.js installation and a simple Express server. W Comparable with Ruby on Rails and many other web frameworks, Express.js comes with a CLI for jump-starting your development process. The CLI generates a basic foundation for the most common cases. -If you followed the global installation instructions in the installation section, you should be able to see the version number 4.15.0 if you run `$ express -V` from anywhere on your machine. If we type `$ express -h` or `$ express --help`, we should get the list of available options and their usage. The list of options is broken down below to serve readers as a reference. +If you followed the global installation instructions in the installation section, you should be able to see the version number 4.15.0 if you run `$ express -V` from anywhere on your machine. If we type `$ express -h` or `$ express --help`, we should get a list of available options and their usage. The list of options is broken down below in this section to serve you, my dear readers, as a reference. To generate a skeleton Express.js app, we need to run a terminal command—`express [options] [dir|appname]`—the options for which are the following: -- `-v`, `--view `: add view support (dust|ejs|hbs|hjs|jade|pug|twig|vash) (defaults to pug) -- `-c `, `--css `: add stylesheet `` support, such as [LESS](http://lesscss.org) (), [Stylus](http://learnboost.github.io/stylus) () or Compass() (by default, plain CSS is used) -- `--git`: add .gitignore -- `-f`, `--force`: force app generation on a nonempty directory +- `-v`, `--view `: Add view support (dust|ejs|hbs|hjs|jade|pug|twig|vash) (defaults to pug) +- `-c `, `--css `: Add stylesheet `` support, such as [LESS](http://lesscss.org) (), [Stylus](http://learnboost.github.io/stylus) () or Compass() (by default, plain CSS is used) +- `--git`: Add .gitignore +- `-f`, `--force`: Force app generation on a nonempty directory If the dir/appname option is omitted, Express.js creates files using the current folder as the base for the project. Otherwise, the application is in the folder with the name provided. -Now that we're clear with the command and its options, let's go step by step to create an app with the scaffolding: +Now that we're clear on the `express` Express Generator command and its options, let's go step by step to create an app with the scaffolding: 1. Check the Express.js version, because the app-generating code is prone to changes. 2. Execute the scaffolding command with options. @@ -313,14 +313,13 @@ $ cd express-styl && npm install $ DEBUG=my-application ./bin/www ``` -Open the browser of your choice at and you'll see "Express Welcome to Express" styled with a CSS which is coming from a stylus file. If you go to , then you'll see "respond with a resource". Everything is working. You created an Express app with Stylus support. +Open the browser of your choice at and you'll see "Express Welcome to Express" styled with a CSS which is coming from a Stylus file (`.styl`). If you go to , then you'll see "respond with a resource". If everything is working, then kudos, you've created an Express app with the Stylus support. ![alt](media/image5.png) ***Figure 2-5.** The result of using Express.js Generator* -If you don't have computer in front of your right now, here's the full code of `express-styl/app.js` using Express.js Generator v4.15.0. The server file has routes from `routes` folder, stylus and a rudimentary error handler. You know I don't like semicolons. The `;` and `var` style is preserved from the code generated by the tool. - +If you don't have computer in front of you right now, here's the full code of `express-styl/app.js` using Express.js Generator v4.15.0. The server file has routes from the `routes` folder, Stylus, and a rudimentary error handler. You know I don't like semicolons. The `;` and `var` style are preserved from the code generated by the tool. ```js const express = require('express'); @@ -373,7 +372,7 @@ app.use(function(err, req, res, next) { module.exports = app; ``` -The Express app is exported with `module.exports` and is launched with `listen()` in the `bin/www` file. Let see main parts of the server file app.js which was created by the Express Generator. +The Express app is exported with `module.exports` and is launched with `listen()` in the `bin/www` file. Let's see the main parts of the server file `app.js` that was created by the Express Generator. ## Routes in Express.js @@ -405,7 +404,7 @@ app.use((req, res, next) => { }) ``` -That's right. The middleware is just a function with three argument. Two of which are good old friends: request and response. Then third argument is a callback which is invoked when all is done.: +That's right. The middleware is just a function with three argument. Two of which are good old friends: request and response. Then third argument is a callback that is invoked when all is done: ```js @@ -414,7 +413,7 @@ app.use((req, res, next) => { }) ``` -Developers can also finish the response with `send()` or `end() ` or `render()` or any other Express method, or pass an error object to the `next()` callback: +Developers can also finish the response with `send()`, `end() `, `render()` or any other Express method, or pass an error object to the `next()` callback: ```js app.use((req, res, next) => { @@ -426,27 +425,27 @@ app.use((req, res, next) => { }) ``` -Let's take a look at another example which has some logic to deal with a query string data (`req.query` object): +Let's take a look at another example that has some logic to deal with a query string data using the `req.query` object: ```js app.use((req, res, next) => { if (req.query.id) { - // process the id, then call next() when done + // Process the id, then call next() when done else if (req.query.author) { - // same approach as with id + // Same approach as with id else if (req.query.id && req.query.ref) { - // process when id and ref present + // Process when id and ref present } else { next(); } }); app.get('/about', (req, res, next) => { - // this code is executed after the query string middleware + // This code is executed after the query string middleware }); ``` -What's useful is that each `req` or `request` object in the *subsequent* middleware functions or request handler functions (i.e., routes) is the same object for the same request. This allows developers to decorate a refernce or a value. For example, by having this middleware we can ensure that all subsequent middleware and routes **have access to `db`**: +What's useful is that each `req` or `request` object in the *subsequent* middleware functions or request handler functions (i.e., routes) is the same object for the same request. This allows developers to decorate a reference or a value. For example, by having this middleware we can ensure that all subsequent middleware and routes *have access to `db`*: ```js app.use((req, res, next) => { @@ -466,7 +465,7 @@ app.post('/users', (req, res, next) => { // use req.db or req.articles }) ``` -Back to the `app.js` file. The request handler for the root route, i.e., `/` is straightforward (`routes/index.js`, in this case). Everything from the HTTP request is in `req` and it writes results to the response in `res`. Here's `routes/index.js`: +Back to the `app.js` file. The request handler for the root route, that is `/`, is straightforward (`routes/index.js`, in this case). Everything from the HTTP request is in `req` and it writes results to the response in `res`. Here's `routes/index.js`: ```js var express = require('express'); @@ -515,30 +514,30 @@ app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); ``` -The middleware includes pass-through functions that either do something useful or add something helpful to the request as it travels along each of them. For example, `bodyParser()` and `cookieParser()` add HTTP request payload (`req.body`) and parsed cookie data (`req.cookie`), respectively. And in our `app.js`, `app.use(logger('dev'));` is tirelessly printing in the terminal pretty logs for each request. In Express.js 3.x many, of these middleware were part of the Express.js module, but not in version 4.x. For this reason the generator declared and included, and we installed additional modules like `static-favicon`, `morgan`, `cookie-parser` and `body-parser`. +The middleware includes pass-through functions that either do something useful or add something helpful to the request as it travels along each of them. For example, `bodyParser()` and `cookieParser()` add HTTP request payload (`req.body`) and parsed cookie data (`req.cookie`), respectively. And in our `app.js`, `app.use(logger('dev'));` is tirelessly printing in the terminal pretty logs for each request. In Express.js 3.x, many of these middleware modules were part of the Express.js module, but not in version 4.x. For this reason, Express Generator declared and included in `app.js` and `package.json`, and we installed with npm additional modules like `static-favicon`, `morgan`, `cookie-parser` and `body-parser`. -## Configuration of an Express.js App +## Configuring an Express.js App -Here is how we define configuration statements in a typical Express.js app (the `app.js` file) with the usage of `app.set()` methods which take the name as a first argument and the value as the second: +Here is how we define configuration statements in a typical Express.js app (the `app.js` file) with the use of `app.set()` methods, which take the name as a first argument and the value as the second: ```js app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug'); ``` -And then in the `bin/www` file, you will see the statement which saves the value of the port which will be used later during the server bootup. The value is coming either from the environment variable or the hard coded value of 3000 as a fallback when the environment variable `PORT` is undefined: +And then in the `bin/www` file, you will see the statement that saves the value of the port, which will be used later during the server bootup. The value is coming either from the environment variable or the hard-coded value of 3000 as a fallback when the environment variable `PORT` is undefined: ```js app.set('port', process.env.PORT || 3000); ``` -An ordinary setting involves a name, such as `views`, and a value, such as `path.join(__dirname, 'views')`, the path to the folder where a templates/views live. +An ordinary setting involves a name, such as `views`, and a value, such as `path.join(__dirname, 'views')`, the path to the folder where templates/views live. -Sometimes there is more than one way to define a certain setting. For example, `app.enable('trust proxy')` for Boolean flags is identical (aka, sugar-coating) to `app.set('trust proxy', true)`. The Chapter 11 explains why we might need to trust proxy. +Sometimes there is more than one way to define a certain setting. For example, `app.enable('trust proxy')` for Boolean flags is identical (a.k.a., *sugar-coating*) to `app.set('trust proxy', true)`. Chapter 11 explains why we might need to trust proxy. ## Pug Is Haml for Express.js/Node.js -The Pug template engine is akin to the Ruby on Rails’ Haml in the way it uses whitespace and indentation, such as `layout.pug`. +The Pug template engine is akin to the Ruby on Rails’ Haml in the way it uses whitespace and indentation, such as `layout.pug`: ```pug doctype html @@ -550,13 +549,11 @@ html block content ``` -Yes, it might look weird and yes, you might [hate it](https://webapplog.com/jade) in the beginning because of a missing white space that breaks your app but believe me Pug is awesome... when you know it. Luckily there's a whole chapter dedicated to templates and you can learn Pug in there. - -Other than that, it's possible to use a full-blown JavaScript code inside of Pug templates with the `-` prefix. More information on Pug and Handlebars template engines is in Chapter 4. +Yes, it might look weird, and yes, you might [hate it](https://webapplog.com/jade) () in the beginning because of a missing white space that breaks your app, but believe me: **Pug is awesome...** when you know it. Luckily, there's a whole chapter (Chapter 4) dedicated to templates, and you can learn Pug in there. -## Conclusion About Scaffolding +## Final Thoughts Scaffolding -As you've seen, it's effortless to create web apps with Express.js. The framework is splendid for REST APIs as well. If you feel like the settings and other methods mentioned in this chapter just flew over your head, don't despair! Pro Express.js [2014 Apress] is dedicated solely to the Express.js, and its interface and can server as a good reference. For now, the next step is to create a foundation for our project: the Blog app. +As you've seen, it's effortless to create web apps with Express.js. The framework is splendid for REST APIs as well. If you feel like the settings and other methods mentioned in this chapter just flew over your head, don't despair! *Pro Express.js: Master Express.js: The Node.js Framework For Your Web Development* (Apress, 2014) is dedicated solely to the Express.js, and its interface and can server as a good reference. This book published in 2014 is still relevant in 2018 and will be in 2019 because the book covers Express version 4 and its still the latest version because this version is very mature and "complete". Get the book on Amazon: . For now, the next step is to create a foundation for our project: the Blog app. # The Blog Project Overview @@ -574,71 +571,73 @@ Our Blog app consists of five main parts from the user perspective: From a developer's point of view, the app has the following elements: -- *Main file* `app.js`: settings, inclusions of routes, and other important logic. This is where we run when we start the server. -- *Routes*: all the logic related to pages and abstracted from `app.js` based on functional meaning, such as getting the data from the database and compiling the data into HTML -- *Node.js project file* `package.json`: dependencies and other meta data -- *Dependencies in* `node_modules`: third-party modules installed via `package.json` -- *Database*: an instance of MongoDB and some seed data -- *Templates*: the `*.pug` files -- *Static files*: such as `*.css` or browser `*.js` -- *Configuration file* `config.json`: security-insensitive application-wide settings, such as app title +- *Main file* `app.js`: Settings, inclusions of routes, and other important logic. This is the file we typically run with `node` to start the server. +- *Routes*: All the logic related to pages and abstracted from `app.js` based on functional meaning, such as getting the data from the database and compiling the data into HTML +- *Node.js project file* `package.json`: Dependencies and other meta data +- *Dependencies in* `node_modules`: Third-party modules installed via `package.json` +- *Database*: An instance of MongoDB and some seed data +- *Templates*: The `*.pug` files +- *Static files*: Such as `*.css` or browser `*.js` +- *Configuration file* `config.json`: Security-insensitive application-wide settings, such as app title -Although somewhat primitive, this application contains all the CRUD() (create, read, update, and delete) elements of modern web development. In addition, we use two approaches in Blog when sending the data to the server: +Although somewhat primitive, this application contains all the CRUD (create, read, update, and delete) elements of modern web development. In addition, we use two approaches in Blog when sending the data to the server: 1. Submit data via traditional forms *with* full page refresh 2. Submit data via REST API (AJAX HTTP requests) *without* page refresh -The source code for this mini-project is under a `ch2/hello-world` folder of `practicalnode` GitHub repository: https://github.com/azat-co/practicalnode. +The source code for this mini-project is under the `ch2/hello-world` folder of `practicalnode` GitHub repository: . ## Submitting the Data -The first approach is traditional and is considered more search engine optimization friendly, but it takes longer for users (especially on mobile) and is not as smooth as the second approach (Figure 2-7). +The first approach, which is depicted in Figure 2-7, is called traditional or thick server, and is more SEO (search engine optimization) friendly. With this approach, all HTML is rendered on the server. Almost all of the logic is on the server as well. This is how web was designed to work. This is how all web apps worked in late 1990s. ![alt](media/image7.png) ***Figure 2-7.** Traditional server-side approach* -Sending and receiving data via REST API/HTTP requests and rendering HTML on the client side is used with front-end frameworks such as React, Backbone.js, Angular, Ember, and [many others](http://todomvc.com) () (Figure 2-8). The use of these frameworks is becoming more and more common nowadays because it allows for more efficiency (HTML is rendered on the client side and only the data are transmitted) and better code organization. +However, this traditional approach requires the reloading of the entire webpage. Thus it takes longer for users (especially on mobile) and is not as smooth and snappy as working with desktop apps. For this reason, developers started to move rendering and other logic to clients (browser). This is the second approach called thick client or client-side rendering and depicted in Figure 2-8. ![alt](media/image8.png) ***Figure 2-8.** REST API approach diagram* -Under the hood, virtually all front-end frameworks use jQuery's `ajax()` method. So, to give you a realistic example, the admin page uses REST API end points via jQuery `$.ajax()` calls to manipulate the articles, including publish, unpublish, and remove (Figure 2-9). +Sending and receiving data via REST API/HTTP requests and rendering HTML on the client side is used with front-end frameworks such as React, Backbone.js, Angular, Ember, and [many others](http://todomvc.com) () (Figure 2-8). The use of these frameworks is becoming more and more common nowadays because it allows for more efficiency (HTML is rendered on the client side, and only the data is transmitted) and better code organization. + +Under the hood, virtually all front-end frameworks use jQuery's `ajax()` method. So, to give you a realistic example, the admin page uses REST API endpoints via jQuery `$.ajax()` calls to manipulate the articles, including publish, unpublish, and remove (Figure 2-9). ![alt](media/image9.png) ***Figure 2-9.** The admin page of Blog* -Unlike the previous section of this chapter, which dealt with scaffolding with CLI, in this practical exercise we intentionally wanted to show how to create an Express.js app manually, because it gives us a better understanding of how things really work together in the framework. +Unlike the previous sections of this chapter, which dealt with scaffolding with CLI, in this practical exercise I intentionally wanted to show how to create an Express.js app manually, because it will give you a better understanding of how things really work together in the framework. Let's wait no more, and start by creating our project folders. # Express.js Hello World Example -This is the second and the last hello world example in this book! :-) The goal is to show readers how easy is it to create Express.js apps from scratch without generators, fancy modules and middleware. We'll go through these sections: +This is the second and the last Hello World example in this book! :-) The goal is to show readers how easy is it to create Express.js apps from scratch without generators, fancy modules, and middleware. We'll go through these sections: - Setting up folders -- npm init and package.json +- `npm init` and `package.json` - Dependency declaration - The `app.js` file - Meet Pug - Running the app -## Setting up Folders +## Setting Up Folders -Express.js is very configurable and almost all folders can be renamed. However, there are certain conventions that might help beginners to find their way through many files. Here is a list of the main folders that we use in this chapter, and their meaning: +Express.js is very configurable, and almost all folders can be renamed. However, there are certain conventions that may help beginners to find their way through many files. Here are the two main folders that we use in this chapter, and their meaning: -- `node_modules`: dependencies (third-party modules) live here as well as Express.js and Connect libraries +- `node_modules`: Dependencies (third-party modules) live here as well as Express.js and Connect libraries - `views`: Pug (or any other template engine) files -That's it for now, but if you want to create a few more folders for other examples (that we'll cover in the later chapters), be my guest: +That's it for now, but if you want to create a few more folders for other examples for later chapters, then go ahead and create these: - `routes`: Node.js modules that contain request handlers -- `db`: seed data and scripts for MongoDB -- `public`: all the static (front-end) files, including HTML, CSS, JavaScript (browser), and Stylus (or any other CSS-language framework files) +- `db`: Seed data and scripts for MongoDB +- `public`: All the static (front-end) files, including HTML, CSS, JavaScript (browser), and Stylus (or any other CSS-language framework files) -Let's choose a project folder `hello-world`, and create these directories with Finder or the following terminal command (Figure 2-10): +Let's choose a project folder called `hello-world`, and create these directories with the Finder macOS app or with the following terminal command, which works on macOS and Linux (Figure 2-10): ``` mkdir {public,public/css,public/img,public/js,db,views,views/includes,routes} @@ -652,21 +651,21 @@ Now we're all set to add project metadata with npm. ## npm init and package.json -For this example we will be creating the Express.js app from scratch, i.e., without Express.js Generator. We'll start with defining dependencies with package.json and npm. +For this example we will be creating the Express.js app from scratch, i.e., without Express.js Generator. We'll start with defining dependencies with `package.json` and npm. -npm is used not only as a registry, but also as a dependency management tool. Therefore, it's essential to set up the project file—`package.json`. Although it's possible to create the `package.json` file manually in a text editor, we can use the `$ npm init` command. Run this command in your project folder and answer all the questions (or leave them blank): +npm is used not only as a registry, but also as a dependency management tool. Therefore, it's essential to set up the project file, `package.json`. Although it's possible to create the `package.json` file manually in a text editor, we can use the `$ npm init` command. Run this command in your project folder and answer all the questions (or leave them blank): ``` $ npm init ``` -After the wizard has finished and the `package.json` file is there (don't worry if there's not much information there yet), we can install modules conveniently and add entries to `package.json` at the same time with `$ npm install --save`—for example: +After the wizard has finished and the `package.json` file is there (don't worry if there's not much information there yet), we can install modules conveniently and add entries to `package.json` at the same time with `$ npm install --save`. For example this is how you can install `express`: ``` $ npm install express --save ``` -The previous command uses the latest stable version (4.16.2 as of Dec 2017). We recommend being more specific—which is more robust in the land of the rapidly growing Node.js community—and ask for a specific version: +The previous command uses the latest stable version available on the npm registry at the moment. We recommend being more specific and ask for a specific version using `@`. Specific versions are better because new versions may have some breaking changes and simply will break your code. Specific versions are more robust in the land of the rapidly growing Node.js community. ``` $ npm install express@4.15.4 --save @@ -678,7 +677,11 @@ For the Blog app, we need the following modules, which are the latest as of this - Pug: 2.0.0-rc.4 - Stylus: 0.54.5 -**Warning**: Feel free to update to newer versions. However, your results might vary, because it's very common in the Node.js ecosystem (“userland”) to see breaking changes introduced by new versions. This usually happens unintentionally by the dependency of a dependency. For example, even if we include a specific version of Express.js such as 3.4.5, that module includes Pug with a wildcard `*`, and then on Pug's breaking update, our app will suffer damage. The cure is to commit your `node_modules` folder along with the rest of the source code to a Git repository and use that instead of fetching modules according to `package.json` each time on deployment. Or use npm's shrinkwarp feature. Read more about this issue in Chapter 12. +**Warning**: Feel free to update to newer versions. However, your results might vary, because it's very common in the Node.js ecosystem (“userland”) to see breaking changes introduced by new versions. This usually happens unintentionally by the dependency of a dependency. + +For example, even if we include a specific version of Express.js, such as 3.4.5, that module includes Pug with a wildcard `*`. This means after every `npm i` the latest version of Pug will be downloaded. One sunny wonderful day a new version of Pug will have some breaking update like a removal of a method which your app uses. Boom! Your app will suffer a great damage and will be broken. + +There are several strategies to mitigate such breaking behavior. Most of them involve locking the versions. And one cure is to just commit your `node_modules` folder along with the rest of the source code to a Git repository and use that instead of fetching modules according to `package.json` each time on deployment. That's what we did at DocuSign. We just committed entire `node_modules`. It worked well. Or use npm's shrinkwarp or package-lock features. Read more about this issue in Chapter 12. ## Dependency Declaration: npm install @@ -713,15 +716,15 @@ Let's create the first iteration of `app.js`. ## The App.js File -The `app.js` file is the main file for this example. A typical structure of the main Express.js file consists of the following areas (this may be a partial repeat from an earlier section, but this is important, so bear with me): +The `app.js` file is the main file for this example. A typical structure of the main Express.js file `app.js` consists of the following areas (this may be a partial repeat from an earlier section, but this is important, so bear with me): 1. Require dependencies 2. Configure settings 3. Connect to database (*optional*) 4. Define middleware 5. Define routes -6. Start the server -7. Start workers with clusters (a term spawn workers is also used for this)(*optional*) +6. Start the server on a particular port +7. Start workers with clusters to scale (a term *spawn workers* is also used for this) (*optional*) The order here is important, because requests travel from top to bottom in the chain of middleware. @@ -751,11 +754,11 @@ app.set('appName', 'hello-advanced'); Let's define a few such configurations in `app.js`: -- `port`: a number on which our server should listen to requests -- `views`: absolute path to the folder with template (views in our example) -- `view engine`: file extension for the template files (for example, `pug`, `html`) +- `port`: A number on which our server should listen to requests +- `views`: Absolute path to the folder with template (`views` in our example) +- `view engine`: File extension for the template files (for example, `pug`, `html`) -If we want to use the port number provided in the environmental variables (env vars), this is how to access it: `process.env.PORT`. +If we want to use the port number provided in the environmental variables (*env vars* for short), this is how to access it: `process.env.PORT`. So let's write the code for the settings we listed earlier: @@ -765,27 +768,25 @@ app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug'); ``` -Next comes the middleware section of the application. Middleware is the backbone of the Express.js framework and it comes in two flavors: - -1. Defined in external (third-party)modules, such as `bodyParser.json` from Connect/Express.js `body-parser`: `app.use(bodyParser.json());` -2. Defined in the app or its modules, such as `app.use(function(req, res, next){...});` +Next comes the middleware section of the application. Middleware is the backbone of the Express.js framework, and it comes in two flavors: -Middleware is a way to organize and reuse code, and, essentially, it is nothing more than a function with three parameters: `request`, `response`, and `next`. We'll use more middleware (for example, for authorization and for persistence) in Chapter 6, but for now, its use is minimal. +* Defined in external (third-party) modules, e.g., `app.use(bodyParser.json());` with `bodyParser.json` being imported from `body-parser` +* Defined in the app or its modules, e.g., `app.use(function(req, res, next){...});` -The next components in the `app.js` file are routes. Routes are processed in the order they are defined. Usually, routes are put after middleware, but some middleware may be placed following the routes. A good example of such middleware, found after routes, is error handler. +Middleware is a way to organize and reuse code and, essentially, **middleware is nothing more than a function with three parameters**: `request`, `response`, and `next`. We'll use more middleware (for example, for authorization and for persistence) in Chapter 6, but for now, its use will be minimal. -An illustration in Figure 2-11 shows how an HTTP request is processed. +The next components in the `app.js` file are routes. Routes process requests. An illustration in Figure 2-11 shows how an HTTP request is processed. So the next section of `app.js` is where we define routes themselves (the order in `app.js` matters). The way routes are defined in Express.js is with helpers `app.VERB(url, fn1, fn2, ..., fn)`, where `fnNs` are request handlers, `url` is on a URL pattern in RegExp, and `VERB` values are as follows: -The next section is where we define routes themselves (the order in `app.js` matters). The way routes are defined in Express.js is with helpers `app.VERB(url, fn1, fn2, ..., fn)`, where `fnNs` are request handlers, `url` is on a URL pattern in RegExp, and `VERB` values are as follows: +- `all`: Catch any requests, i.e., all HTTP methods +- `get`: Catch GET requests +- `post`: Catch POST requests +- `put`: Catch PUT requests +- `patch`: Catch PATCH requests +- `del`: Catch DELETE requests -- `all`: catch every request (all methods) -- `get`: catch GET requests -- `post`: catch POST requests -- `put`: catch PUT requests -- `patch`: catch patch requests -- `del`: catch DELETE requests +**Note**: `del` and `delete` methods are aliases in older versions of Express. Just remember that `delete` is a valid operator in JavaScript/ECMAScript, and therefore in Node.js. The operator removes a property from an object, e.g., `delete books.nodeInAction`. -**Note**: `del` and `delete` methods are aliases, just remember that `delete` is a valid operator in JavaScript/ECMAScript, and therefore in Node.js. The operator removes a property from an object, e.g., `delete books.nodeInAction`. +Routes are processed in the order in which they are defined. Usually, routes are put after middleware, but some middleware may be placed following the routes. A good example of such middleware, found after routes, is an error handler. Figure 2-11 shows how a trivial request might travel across the web and the Express.js app, with the dotted lines being the connection inside it. @@ -793,7 +794,7 @@ Figure 2-11 shows how a trivial request might travel across the web and the Expr ***Figure 2-11.** Following a simple request in an Express.js app* -In this Hello World example, remove a single route is used to catch requests of all methods on all URLs (`*` wildcard): +In this Hello World example, a single route is used to catch requests of all methods on all URLs (`*` wildcard): ```js app.all('*', (req, res) => { @@ -801,7 +802,7 @@ app.all('*', (req, res) => { }) ``` -Inside the request handler, a template is rendered (`res.render()` function) with a message `msg` (property of the second argument): +Inside the request handler, a template is rendered with the `res.render()` function using name of the template `index` as the first argument and the data object as a second argument. The data has a message `msg` as the property of the second argument: ```js app.all('*', function(req, res) { @@ -809,20 +810,20 @@ app.all('*', function(req, res) { }) ``` -The `res.render(viewName, data, callback(error, html))` where parameters mean following: +For reference, in `res.render(viewName, data, callback(error, html))` where parameters mean the following: -- `viewName`: a template name with filename extension or if `view engine` is set without the extension is set without the extension -- `data`: an optional object that is passed as `locals`; for example, to use `msg` in Pug, we need to have `{msg: "..."}` -- `callback`: an optional function that is called with an error and HTML when the compilation is complete +- `viewName`: A template name with filename extension or if `view engine` is set without the extension +- `data`: An optional object that is passed as `locals`; for example, to use `msg` in Pug, we need to have `{msg: "..."}` +- `callback`: An optional function that is called with an error and HTML when the compilation is complete -`res.render()` is not in the Node.js core and is purely an Express.js addition that, if invoked, calls core `res.end()`, which ends/completes the response. In other words, the middleware chain doesn't proceed after `res.render()`. `res.render` is highlighted in chapter 4. +`res.render()` is not in the Node.js core and is purely an Express.js addition that, if invoked, calls core `res.end()`, which ends/completes the response. In other words, the middleware chain doesn't proceed after `res.render()`. `res.render` is highlighted in Chapter 4. -Last but not least are the instructions to start the server. In the previous hello app, you saw `app.listen()` but `http.createServer(app).listen()` will work too. It consist of the core `http` module and its `createServer` method. In this method, the system passes the Express.js `app` object with all the settings and routes: +Last but not least are the instructions to start the server. In the previous Hello World app, you saw `app.listen()`, but `http.createServer(app).listen()` will work too. It consists of the core `http` module and its `createServer` method. In this method, the system passes the Express.js `app` object with all the settings and routes: ```js http.createServer(app).listen(app.get('port'), () => { - console.log(`Express server listening on port ${app.get('port')}`); -}); + console.log(`Express server listening on port ${app.get('port')}`) +}) ``` You can also use `https.createServer(app).listen()` for the HTTPS support when you are ready to deploy your server to production. @@ -863,14 +864,14 @@ Before we can run this server, we need to create the `index.pug` file in the `vi Pug is an absolutely amazing template engine that allows developers to type less code and to execute powerfully almost all JavaScript functions. It also supports top-to-bottom and bottom-to-top inclusion and other useful things. Like its brother from the Ruby world, Haml, Pug uses whitespace/indentation as a part of its language. It's a convention to use two-space indentation. -The Pug syntax and its features are covered more extensively in Chapter 4. For now, just keep in mind that the way Pug works is that the first word is used as an HTML tag (HTML element) and the text that follows (a.k.a., inner text), is put inside this element. For example, +The Pug syntax and its features are covered more extensively in Chapter 4. For now, just keep in mind that the way Pug works is that the first word is used as an HTML tag (HTML element), and the text that follows, which is inner text or inner content, is put inside this element. For example, here are two sibling elements `

` and `

` with text inside of them. The space after the Pug elements `h1` and `p` is super important! ```pug h1 hello p Welcome to the Practical Node.js! ``` -Produces the following HTML code: +That produces the following HTML code: ```html

hello

@@ -890,11 +891,11 @@ h1 hello p= msg ``` -There are more advanced examples of Pug included later in this book; but, for now, everything is set for the first demo! +I included more advanced examples of Pug later in this book. For now, everything is set for the first demo! 👀 ## Running the Hello World App -When we run the `$ node app` command and open browsers at , we see what appears in Figure 2-12. +Run the `$ node app` command from the project root. When your app is running you can open a browser at . Now you should see the Hello World text as it appears in Figure 2-12. ![alt](media/image12.png)