16

This is the question mostly asked by the beginners, as I had this question when I was starting out

How to set port for express without needing to hardcode or even choose port yourself? This is the question I had when I was starting out in node and express (I am still a beginner, have lots of things to learn). Things I wanted know other than that included,

  • What is difference between using app.set('port', portNum) and directly using port number in app.listen(portNum)?
Community
  • 1
  • 1
Syed Huzaifa Hassan
  • 776
  • 1
  • 6
  • 22

4 Answers4

25

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 ADMIN_EMAIL=joe@example.com npm start

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

const foo = process.env.FOO;                  //-> "bar"
const adminEmail = process.env.ADMIN_EMAIL;   //-> "joe@example.com"

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": "dev@example.com"
}

testing.json

{
    "port": "5555"
}

production.json

{
    "adminEmail": "admin@example.com"
}

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'));
Ryan Wheale
  • 26,022
  • 8
  • 76
  • 96
  • In addition to this excellent answer, I'd also suggest hardcoding a fallback. This is what I do for local development - it's only in production that I specify a port: const port = process.env.PORT || 3000; – Matt Parkins Nov 22 '18 at 11:59
  • 2
    I personally don't like defining fallbacks in code. I'd rather have everything in a config, with my "default" config holding all of the default values. I prefer the app to fail if a config item is missing so that I can add it to my "default" config properly. To each their own though. – Ryan Wheale May 07 '19 at 17:40
  • @Minsky - absolutely. Once you start adding a whole bunch of variables in the command, you kind of naturally find out about `.env` - which is why I omitted it. I updated the answer to include that aside. Thanks! – Ryan Wheale Dec 18 '20 at 20:30
10

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()?

Community
  • 1
  • 1
Syed Huzaifa Hassan
  • 776
  • 1
  • 6
  • 22
3
  • Unix [1]:
$ PORT=1234 node app.js
  • More permanently (for a login session) [2]:
$ export PORT=1234
$ node app.js
  • In Windows:
set PORT=1234
  • In Windows PowerShell:
$env:PORT = 1234

[1] Process-lived, while the parent process that initiates is still running. If you close terminal, variable dies.

[2] Close terminal, open a new one, variable still alive.

Minsky
  • 2,277
  • 10
  • 19
Shafeeq
  • 31
  • 1
1

config.js

let config = {};

// PORTS
config.port = {};
config.port.alpha = 4050;   // Server 1
config.port.beta = 4051;   // Server 2
.....


module.exports = config;

app.js

const express = require("express"),
    config = require("./config");

....

app.set('port',config.port[process.env.SERVER_NAME]);
app.listen(app.get('port'),function(){
    console.log("Server running at "+app.get('port'));
});

Starting server

SERVER_NAME=alpha node app.js
SERVER_NAME=beta node app.js
Tabish Rizvi
  • 357
  • 2
  • 10