How to set port for express server dynamically?

How to set port for express without needing to hardcode or even choose port yourself?


###Option 1: Environment variable (recommended)

Often times you will deploy your app to a hosting provider like Heroku. Depending on how the host is configured, the system will dynamically set an environment variable and your app will need to get the port from this variable. For example, the hosting provider might run a command like this when it runs your app:

$ PORT=1234 npm start

... and within your code, you can access this variable like this:

const port = process.env.PORT;
app.listen(port);

Pro tip: Most hosting providers let you define custom environment variables too. You can test this locally by creating arbitrary variables like this:

$ FOO=bar [email protected] npm start

...and access those variables from code like this:

const foo = process.env.FOO;                  //-> "bar"
const adminEmail = process.env.ADMIN_EMAIL;   //-> "[email protected]"

Option 2 - environment-specific config files (also highly recommended)

Using a config library like config and/or dotenv allows you to easily manage environment-specific config options. Your folder structure would look like this (note the names of the files):

|- config
   |- default.json
   |- testing.json
   |- production.json
|- src
   |- app.js

You then define your "default" variables and environment-specific variables:

default.json

{
    "port": "3030",
    "adminEmail": "[email protected]"
}

testing.json

{
    "port": "5555"
}

production.json

{
    "adminEmail": "[email protected]"
}

The config library will always use the default variables. When you are on testing it will use the default admin email and a different port. When you are on production it will use the default port but a different admin email. The way you define your "node environment" is like this (notice we use the same name as the JSON config files):

$ NODE_ENV=testing npm start
$ NODE_ENV=production npm start

Pro tip: Your configuration files can reference environment variables too! Continuing with our example from Option 1 above, you can define your production config like this:

production.json

{ 
    "port": "PORT"
}

The config library will look for any environment variables named "PORT" and will use that value. Putting it all together, your final command to run your app might look like this:

$ NODE_ENV=production PORT=47861 npm start

Pro tip: - dotenv can be used alongside the config library for ultimate environment variable management!!


2. What is the difference between using app.set('port', portNum) and directly using port number in app.listen(portNum)?


Express allows you to set application variables using app.set - but this is just a fancy way for defining variables. You can later get the values for these variables using app.get.

Sooner or later, you are going to need to tell your app to listen for traffic on a specific port. You could do something like this:

const app = express();
app.set('port', process.env.PORT);

app.use((req, res) => { ... });
app.listen(app.get('port'));

Answers that I found to my questions

1. How to set port dynamically?

I found out that you can use number 0 in app.listen() to let express select the port randomly, then I soon found out that I now had a problem I didn't know which port to access to know if my server was running or not. So simple answer to that was to output the app.address().port in console so a Simple express server will look like this

let http = require('http');

let express = require('express');
let app = express();

app.use('/', serveStatic('./public'));
app.get('/', (req, res) => {res.render('index')});
let server = http.createServer(app);
server.listen(0, () => {
    console.log(server.address().port)
})

2. What is difference between using app.set('port', 1234) and directly using port number in app.listen(1234)?

In my experience/knowledge (honestly speaking its almost equivalent to zero) I came to believe that, app.set() sets the property in app.locals and allows retrieving of that information later (which is somewhat similar to creating a variable), but I recently read that app.set() allows the value stored to be used in you template engine and other places, which makes it quite different.
What is the difference between setting a property on app.locals and calling app.set()?