Previous Lecture Complete and continue  

  Express.js Configurations and Middleware

Okay, I know you don't know a lot about Express, but trust me that Core HTTP example, it will be useful later. Why? Because Express offers this benefit to developers. With Express we can parse URL parameters and query strings. We can also automatically get response headers into our response. We can better organize routes, and that means our code will be more scalable and other developers will be happy with our work.

Then there is this huge plethora of plugins, also called middleware, available for Express. As I mentioned Express is the most popular Node.JS framework, so it's not a surprise that there are a lot of plugins available for it. With those plugins, you can implement body parsing, request body parsing, authentication, validation, sessions and more and more things, very useful for the web development both traditional apps and RESTful APIs. So how do you install Express JS?

Of course, it's an npm module, so we would use npm. So the command is npm space install space express. I like to add --save, just because that option will add an entry into package.json file. Another good advice, is to use an exact version with an at symbol. The same symbol that you would use in your email. So [email protected] which is the latest version as of this recording.

And then, just to confuse you a little bit, no, I am kidding, there is Express generator. So Express generator, we would install that globally with --global, or -g command. Global is very, very different from when you're not using global, when it's local. So the first approach I showed you, that's where you want to use Express as a dependency. That's where you install it local. This is the majority of the cases.

And then in each case, you would do just once. You would create this command line, which is funny enough and confusing enough, called what we've also invoked with Express, but the name is Express-generator. If it flies over your head, don't worry. I'll explain it to you later.

For now, remember, the generator or the scaffolding command line two, we need to use -g. This is how you would use the generator. You would go into your command line and type express. Then you would type a space and the name of your application, todo-list-app in my case. This will create a lot of folders and files for you. It's a boilerplate code. It has some basic structure, and it also can pass some options, for example, what CSS library to use or what templating language to use. Then you would want to navigate into that folder and install all of the dependencies, Express itself.

Remember, Express the dependency that goes into local folder. And then, depending on whatever CS says, language you've chose, Sass or LESS, or the template engine, for example Jade. Npm would install that, taking the data from package.json. And then to run the app after you've installed everything, you would execute node app. This is the structure. This is three folders and one file that the generator will create, so app.js is our main file. That's where the entry of our application, the initiation and all other important logic, starts.

Then in the public we have our static files. So if you're building a single page application, that's where it goes. Files like html, java script for the browser, and CSS files, they all go to the public folder. The public folder will be exposed, so we don't want to put any Node.js files there. Then the routes folder. This is where we would need to organize our routes, for example, users.js for the users resource, or accounts.js for accounts resource, and then the usual contain template that can be processed by a template engine, for example Jade templating engine, or handlebars. Those files goes into views.

All of this folders can be configured. This is the advantage of Express. There's no convention. Everything can be configured. What about app.js? It has five distinct parts. We'll start with imports and instantiations. So we import whatever files we need to import, or modules I should say. Then we configure our Express app. Then we would utilize middleware, apply them, most likely from the imported modules. Then we would create the routes, or we would apply the routes imported from our own modules from the routes folder. And then finally we would boot up our server.

So first things first, we're starting with configuration and the importation. To import basically use require to instantiate app equals express. Express uses functional inheritance or function factory, as it's also called. Then on the third line you would see app.set. This is the syntax for configuring settings. Settings could either be systems settings, means Express uses them, or some arbitrary. I just made up this PORT value, because I want to store this number for future uses. But views and view engine, that's the system's settings. Express uses them for its purposes.

For example, views, that's the name of the template that we want to use. Instead of views, as you've seen on the previous slide, I want to use templates. Then all I need to do is just rename my folder which my generator created. Or if I didn't use the generator, even better. I'll just create that folder template. And then we have view engine, which will enable Express.js to require that module, Jade, and also search for the files with this extension when we render template. Obviously most of us will be building RESTful APIs, so the templating agent is not that important nowadays in the modern web development.

The next topic is the Node.js middleware pattern. Middleware is used a lot in Express, but it's not exclusive to Express. It's just a common Node.js pattern. What it does, it enables continuity. If we have multiple pieces of logic, we can stitch them together with this pattern. So what is a middleware? Middleware is just a function. This is my demystification. It's nothing complex, very easy, it's just a function. Function, that one of the arguments of which, it's a callback that will be the next function.

And then in the next function again, we have that callback which will be the next function so far, so on. So this enable us to chain different functions together, and most of them would be in the middle, hence the name middleware. So next it's a callback. We'll run some code, and then we invoke next with or without parameters; it doesn't matter as long as we invoke that callback. So the main idea here is the continuity and that the orders matter. So obviously middleware1 would be executed before middleware2, et cetera. And then in the beginning, we have our request, and at the end, we have our route and then the response. So this is a problem when we try to organize our code and create different modules for different routes.

For example, app.js we create a database, we connect to the database, and we have this object database. We need to use that in our, let's say users module. How would we pass it? I would maybe enter require, we can also pass that reference, right? This might work. But there is a better way. The better way would be to use middleware. Oh, and by the way, Express leverages the Connect framework which has a lot of middleware. So that's another advantage. Okay, so how do we actually apply middleware? In order for us to apply middleware, we need to utilize app.use. And then we just path that middleware. Obviously, we need to define it. In the next slide, I'll show you how to do it. But for now, app.use, we use this for all middleware. So the middleware order matters.

These are two middlewares that I imported from modules, morgan and body parser. And then I applied them in the order. So first logger will get the request, and then the body parser will get the request, not the reverse. So there are two catergories of middleware. One, you've already seen, like body parser, those are npm modules. We need to install them and then require. And then we have custom middleware. Custom middleware could be just a function in the same file. It could be your own small file, small, tiny module somewhere in your file system. This is how you create your own middleware.

All you need to do is create this function with three arguments: request, response, and next. Remember next? That's right. That's what we need to call at the end. And then request and response, we can do a lot of interesting things with those two objects. We can also declare the middleware ride in the app.use. So the previous example was using a reference to store the function, and then use the name. In this example, we don't have a name. It's anonymous function definition. So back to the database problem. If this is the solution, which I think is more elegant. It's more scalable; it's just brilliant.

So what we see here request is always the same object in the lifecycle of a single client. I will repeat that. Request is always the same object in the lifecycle of a single client request to the Express server. So when the request is traveling, and that's a single request, that request object is always the same in all the middleware. And then maybe we have one route match. Maybe we have more than one that request object in route, it's also the same. So because of the same object, we can create a new property, like a database, and assign our database reference. And this code will work in any module, any file, because it's just a function. We're passing an argument, which is request, and it has this property. What are some of the most powerful and useful Connect and Express middleware?

Obviously it's the body parser, because we can pass our payload. Most RESTful API servers will need that. Then gzip compression, it's a good idea to have on compression. Connection-timeout, that will set some timeout for your requests, cookies, sessions via Cookies store. Then CSRF, that's a security token. Errorhandler is a basic boilerplate, errorhandler middleware. Express-session, that's what we should use instead of session cookie, because this session will store only the session ID-ing the cookie, not the session itself. So Express session's more secure by default it works with Memory store, but it's very easy to plug RADIUS or MongoDB as a persistent storage. And then method-override, that's for the client that do not support DELETE or PUT. It works with GET and POST only. Morgan that's for server logs. Response-time will calculate the response time and add that to the header. Serve-favicon that's the tiny, bitty icon in the uro browser.

Serve-index, that's a web interface if you want to see the content of your folder. Obviously, don't make it on your Node.js files, because your code will be exposed. And then service-static, that's what we use for the public folder. That's how we store the static content. Then vhost is another useful module. So if you following in the slides, all of those names, they're clickable, and that will take you to the better documentation and some examples. So a few more of the popular middleware. QS is analogous to Query, but it uses nested objects in a Query stream. The important middleware, if you want to do the file uploads, connect-busboy and connect-multiparty. And then one of my favorite, express-validator. That's what we can use to validate, request, body, or I can input data. And then passport, it's a brilliant, brilliant module. It has a lot of strategies for all work for pretty much any major service, like Facebook, Google, Twitter, et cetera.

So all we need to do is get passwords and get that strategy, put your API keys, and boom, it's working. Magic! Okay helmet security headers, that's where you're implementing your application. It's a good foundation to have for security. It adds some security headers and security headings for your application. It's not fail-proof, but it's a good start. So, you might take your security seriously, and helmet is a good start. CORS, cross-origin and research sharing, that's when your single page application is hosted on a different domain, so you need those, you need CORS. And then connect-redis, that's to connect to the Redis database.

A little bit about templating engines, so as I've mentioned, view engine of how we can set the templating engine, but what it actually does, Express under the hood executes this app.engine. So we can also call that function directly. And what it's doing, it's requiring Jade. And then Jade has this interesting method. It's called __express. And you would see a lot of template engines having this method, because that's considered common convention. If a module supports Express, it needs to implement this method, if the module is a template engine. And then if you, for some reason, need to use a template engine which does not support this method, look for a method that have this signature: path, option, and a callback. And then you can just find that pattern name in that module and put it in app.engine. But it's very, very rare that you would find a template engine that does not support an Express function. Okay, so we covered configurations and middleware.

Let's skip routes for now and proceed to the bootup. The bootup is very easy. It's very similar to the Core HTTP. We use createServer, we pass our app, because app it's an inset of HTTP server. And then we actually do server.listen. An obviously, we need to pause the port which is saved in the settings. That's why I needed it there. There is an alternative way which is a little bit more eloquent. We use app.listen will also work. So how do you launch the app? So we're done with the code for now. You can use node. But a better way would be nodemon, node-dev, forever, or pm2. Pm2 is probably the rockstar here, because it has load, balance, and a lot of other cool stuff. And can scale very, very beautifully.

What about nodemon and node-dev and forever? They are better than just node, because they would listen to your file changes. Let's say you're developing, you're still in development mode, every time you make a change, you need to restart the server manually, which becomes very tedious. So we want to save the time, so we want to use nodemon or node-dev for that. So as you witnessed, Express.js is awesome.

0 comments