When you’re actively developing your Node.js code, you want the turn-around time to be fast and its reliance on external systems to be low. So far we’ve been keeping things this way, using the isDev variable to occasionally make choices about whether to do things the development way.
In this section, you’ll take the remaining steps to prepare the application to run in production mode. Once everything is in place, we’ll clean out the project and reinstall the dependency modules to perform a clean production test run.
The first thing we need to switch out is how session data is stored. In a production environment, you’re usually better off storing sessions on a service like Redis than on the filesystem.
Redis is a fast, open source, in-memory key/value store.[103] You can use it as a database, cache, or message broker, and you can control when and if it synchronizes to disk.
We’re going to use Redis to store session information when NODE_ENV is set to production. To do this, you’ll need to install Redis, then install the Redis session module, add a production.config.json file, and wire it up in your server.js file. Let’s get started.
The first step to using Redis to store session info is to install the Redis service. This varies by platform, but the Redis Download page has binaries for most popular operating systems.[104] If you’re using Ubuntu, you can install the Redis server and command-line utilities from the repositories using apt:
| | $ sudo apt install redis-server redis-tools |
On Mac OS X with homebrew, it’s even easier:
| | $ brew install redis |
Although the Redis project does not itself distribute a Windows build, you can get one from the Microsoft Open Tech group on GitHub.[105]
Once you’ve installed Redis, you can test if it’s working with the redis-cli command-line program.
| | $ redis-cli |
| | 127.0.0.1:6379> ping |
| | PONG |
| | 127.0.0.1:6379> quit |
If you see this, great! You’re ready to create a production config to point to it. Start by copying your development.config.json to production.config.json. Ideally, at this point you’d switch over all the configuration settings to more permanent production values. But for now, all we need to do is add the Redis configuration values.
Open your brand-new production.config.json file for editing, and add a section for Redis like so:
| | "redis": { |
| | "host": "localhost", |
| | "port": 6379, |
| | "secret": "<your Redis secret here>" |
| | } |
To connect to Redis, your server needs to know where to find it (the host and port). The default TCP port that Redis uses is 6379. The secret is used in the same way the FileStore used it earlier in the chapter—to sign cookies. If you ever need to simultaneously sign all users out of the system, changing the secret will do it! Once you save the production.config.json file, you’re ready to wire it up to your server.
At this point you have Redis installed and a production.config.json that contains settings for it. Now you’re ready to install the connect-redis module and use it for session storage. Use npm to install it.
| | $ npm install --save -E connect-redis@3.3.2 |
Next, open your server.js file for editing and find the comment that reads, “Use RedisStore in production mode.” Add the following code there.
| | // Use RedisStore in production mode. |
| | const RedisStore = require('connect-redis')(expressSession); |
| | app.use(expressSession({ |
| | resave: false, |
| | saveUninitialized: false, |
| | secret: nconf.get('redis:secret'), |
| | store: new RedisStore({ |
| | host: nconf.get('redis:host'), |
| | port: nconf.get('redis:port'), |
| | }), |
| | })); |
This code should look familiar to you based on its similarity to setting up the FileStore class for storage. First we pull in the RedisStore class attached to the expressSession object. From there, we call app.use, passing in the expressSession middleware with its matching configuration.
This time, we set saveUninitialized to false. We don’t want to store uninitialized sessions in production mode—we’d rather wait until the user authenticates to bother saving session information. And rather than hard-coding the secret, we pull it in through nconf.
For the store, we pass in a new instance of RedisStore, configured with settings from nconf. The connect-redis module supports additional options,[106] but these are all we need for this application.
Save your server.js file. All of the code is in place to run in production mode now except the dist directory assets. It’s time to do an end-to-end test of production mode.
At this point, all of the code is in place to run in production mode. It’s time to tell webpack to build the assets.
Head to a terminal and invoke npm run build.
| | $ npm run build |
You can confirm that it worked by taking a peek at the dist directory.
| | $ tree -F ./dist |
| | dist |
| | ├── 674f50d287a8c48dc19ba404d20fe713.eot |
| | ├── 89889688147bd7575d6327160d64e760.svg |
| | ├── 912ec66d7572ff821749319396470bde.svg |
| | ├── b06871f281fee6b241d60582ae9369b9.ttf |
| | ├── bundle.js |
| | └── index.html |
| | |
| | 0 directories, 6 files |
Now we’re ready to try a production run.
To make sure everything is working according to plan, the safest thing is to remove and reinstall all of the dependency modules in production mode. That way you don’t accidentally depend on something that you forgot to save to your package.json file.
Start by removing the contents of the node_modules. Be careful not to delete something else by accident!
| | $ rm -rf node_modules |
Now run npm install but with NODE_ENV set to production. This will prevent npm from installing any devDependencies.
| | $ NODE_ENV=production npm install |
And finally, start up the server in production mode.
| | $ NODE_ENV=production npm start |
| | |
| | > b4@1.0.0 start ./code/fortify/b4 |
| | > nodemon --ignore './sessions' server.js |
| | |
| | [nodemon] 1.12.1 |
| | [nodemon] to restart at any time, enter `rs` |
| | [nodemon] watching: *.* |
| | [nodemon] starting `node server.js` |
| | Ready. |
All that’s left is to try it out! Open http://b4.exampl.com:60900/ in a browser and see if it all works. You should be able to sign in, add bundles, and sign out. Woo! Let’s recap where we went in this chapter.