When we want to change some options in our application, we need to redeploy it for any small change. If we make things configuration-driven, we can change things simply by restarting the application.
- [Teacher] Section 1. In this section, we'll be learning how to configure nconf. nconf is an open-source tool which is used a configuration module. We familiarize ourselves with Winston. It is a logging library which we'll use to log various aspects of our application. And installing Nunjucks, which is an alternative templating language to be used with Express.
config.js is a configuration module that helps make your application flexible. Configuration is important, as it helps keep magic numbers out of our application. We can even create multiple levels of configuration that override each other, providing smart defaults whilst you keep your production configurations secure. It's worth mentioning that there are alternatives to nconfig out there, but nconfig is the biggest library available. It has thousands of users, and is developed by Flatiron, a well-respected node development company.
Let's start with an empty Express application. To do this, we need to install Express Generator. Once that's installed, we can just run Express to have an application generated for us. Don't forget to run npm install to install the dependencies for our application. At the moment, the port our application runs on can either be set in the environment or it's hard-coded to port 3000.
This works well for single-wire value like the port to listen on, but it can become a little hard to follow with lots of configuration options. Imagine that we have some logging in our app, where we want to change from logging debug messages to only logging errors. Each time we want to change these values, we need to either change our environment or redeploy our application. Wouldn't it be much easier if we just had to change a config file and restart our app? First, we need to install the package from npm.
To do that, we use npm install nconfig. Once it's downloaded, we can start using it. nconfig comes with five different ways to load configuration: argv, which is the command line; env, which comes from the system environment; file; defaults; and overrides. defaults and overrides are ways to specify values directly in your application. Of the five, argv, env, and file are the more interesting.
You can specify which order they would be read from, meaning that you can, say, read from argv, then, if it doesn't exist in there, try the environment, then our config file, then finally, use the defaults we specified if you can't find it anywhere else. So for example, if we have a port number defined in our defaults, in a config file, and in the environment, the one from the environment would be used as it overrides the file and default options.
Let's replace the existing hard-coded values in our app so that they read from nconfig instead. To do this, we'll utilize nconfig.defaults. But first, we need to include our module so that we can start using it. So let's edit app.js. At the end of our imports, we'll add var nconf equals required bracket nconf close bracket. Next, we'll add a call to nconfig.defaults to set some of the default values.
The hardest part about this is trying to think of the names for the configuration options. Here, I've created the http namespace and specified the port we are going to listen on, in this case, port 3000. Next, we need to update our www binary to this value. So let's open bin/www and look for where we set the ports. So app.set, port, we need to change this to nconf.get http colon port.
Colon is the namespace separator for nconf. We can also delete the line before, because we don't need it anymore, and save our file. As this is a different file, we don't actually have access to nconf. So let's jump to our requires and add nconf just like we did in app.js. Express previously used app.get('port') to say which port the service should listen on, but recently, they have changed it to just using a port variable.
Let's change that back. Now we should be able to run our app just like normal. It should work just the same. The debug variable here is saying enable Morgan logs. Morgan is the logger for express.js. So it says anything in the mastering-express-application-development namespace, I want to see. As you can see, our Express server is now running, and it's listening on port 3000.
Now that we've got nconf installed and we're using it, let's start customizing things. I've created a file called config.json that has the same layout as our own config defaults block, an http namespace and port. But this time, I've set the port to 8000 rather than 3000. This is to show that the port will change if we tell our application to use the config file. Let's tell nconfig that we want to use this configuration file.
So back to app.js, and before we specify our defaults, we want to say our configuration file has a higher precedence. So we declare it before the defaults block and here. I've just used nconfig.file and passed in config.json. You can pass in a path to any file that you like. If we save that, and then we start our application again, we can see that instead of listening on port 3000, we are now listening on port 8000.
Congratulations! We've got two levels of configuration being loaded. But why stop there? Our config file should override defaults, but we should have a way to override that, too. Let's use environment variables to do this. Unfortunately, the colon character that nconf uses for namespacing isn't valid as part of a variable name. So when we enable nconf.env, we need to specify a new delimiter. By convention, we use a double underscore.
Just like always, when we make a change, we want to make sure that it works. So let's go and restart our application. As expected, it's currently running on port 8000. If we change this and add an environment variable, our namespace is http, and then we add our double underscore, and we type port. You must set this to 8001. As you can see, our application is now listening on port 8001.
Finally, let's have a look at command-line options. These are values that the user can set that will override everything else other than the overrides section. When adding a command-line option, you tell it what the command-line flag should be, what configuration option it translates into, and the description of the flag. Again, we want to prove that it works. So let's start our application normally. It's still port 8001, as it's coming from the environment.
But if we pass our -p flag, as you can see on port 8002, we can see that the port that the application is now listening on has changed. This is because the command-line flags have a higher precedence than the environment. Sometimes, though, there's just some values that they don't anyone to change at the minute. Eventually, they might become config options, but for now, you want full control over them. This is where nconf.overides comes in.
You can use config values just like you would normally, and then hard-code the values using nconf.overrides, safe with the knowledge that no one else can change it. And then, when you're ready for the things to become configurable, you can remove the overrides section. Again, we want to make sure that things are working. So let's start our application. That reminds that we now have our default of port 3000, our configuration of port 8000, our environment of port 8001, and our command-line flag of port 8002.
But when we start our application, it's listening on port 9000, which is what we specified in our overrides section. As we don't want to override the http port at the moment, I'm just going to remove this and save the file. Whilst developing, we are going to be working with the config files default, so our application will be running on port 8000. nconfig lets you change your application's behavior without having to redeploy it every single time.
It supports multiple levels of inheritance, as well as overrides for fixing options that you don't want people to change temporarily. Next time, we're going to take a look at Winston, a logging framework.
To start, author Michael Heap creates a new Express application, showing how to configure it and increase application visibility with logs. Explore Express along with various libraries that will help improve your development experience. Then take a look at technologies such as SSL and nginx, and work through deploying your application to production in a secure and scalable way. Michael also introduces some existing open-source Express projects and reviews how they are structured, to help you organize your own applications in a systematic way. By the end of the course, you'll be familiar with a wide range of new Express tools and libraries, all of which will help you deliver the best value to your customers.
- Consuming an API
- Showing results on a webpage
- Caching requests in memory
- Refactoring for testing
- Mocking to remove dependencies
- Spying with Sinon.JS
- Sending and receiving data in real time
- Mounting subapplications
- Serving content conditionally for AJAX
- Securing your app
- Improving performance
- Examining large-scale Express apps: Ghost.org and Balloons.IO