Over the past few months I've found myself spinning up tons of new servers and walking through the process of pushing express apps live.
Because this process always comes at unexpected times, I've never bothered documenting the steps it takes to get a blank box running express. Surprisingly it seems as though few have bothered to walk through every step involved in a single place, and most express tutorials contain outdated information which likely leads to headaches for newcomers.
I'll be walking through an ExpressJS setup with the tech I always opt for.
- NodeJS & NPM
Prep your server by installing the latest updates:
$ apt-get update $ apt-get upgrade -y
Installing NodeJS is a bit tricky on Debian-based systems (like Ubuntu). NodeJS is best built from nodesource, which provides access to binary distributions of Node for free. Find the version of Node you'd like to install from the nodesource Github repository and install as such:
$ curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - $ sudo apt-get install -y nodejs $ sudo apt-get install gcc g++ make $ sudo npm install -g npm@latest
We also run
sudo npm install -g npm@latest to get the latest version of NPM for our version of Node, which means we're all set up from the Node side.
Nginx will be our webserver of choice to serve our app to users over HTTP. Well install this now, but come back to configuring this later:
$ sudo apt-get install nginx
Express & Express Generator
The Express NPM package contains the entirety of the ExpressJS framework, which we'll install globally on our system by passing the
-g flag. We'll also install Express-Generator, which is a useful CLI for starting up Express apps:
$ npm install -g express $ npm install -g express-generator
Create an App
Now we get to the fun stuff.
$ cd to the directory you'll be using to contain your apps, such as
/var/www. When we use
express-generator in this directory, we'll be initializing a new express project will most of the common boilerplate setup preconfigured.
We're going to start our app in
/var/www/ by navigating to that directory and kicking off
$ cd /var/www $ express --view=hbs --css=less myapp
Express-generator prompts you to pass arguments to automatically configure your project for you. We're able to specify which CSS preprocessor and templating system we prefer this way. I'm going to create a project using Handlebars and LESS as my weapons of choice, but your choice of templating engine and style preprocessor is entirely up to you. Running
$ express -h will give you a full breakdown of these options, as well as a few other helpfucl commands such as adding a .gitignore file:
Warning: common bug ahead
If your life sucks, running express generator may have given you this error:
/usr/bin/env: ‘node’: No such file or directory
This is an issue with Debian distributions of linux which treat
nodejs as separate filepaths. To alleviate this, create the following symbolic link:
ln -s /usr/bin/nodejs /usr/bin/node
Start Building Your App
Inside your project directory run npm install to install all dependancies for your project. This will look at the
package.json file that express-generator created and will install the corresponding node modules.
$ cd /var/www/myapp $ npm install
The contest of your app's directory should be structured as so:
Before creating your Nginx config, it is best to verify which port express will be running on. The entry point of modern ExpressJS apps is a file known as /bin/www, which is the file Nginx looks for to kickstart your app. Check out that file and look for the
port variable, so we know which port our app is listening on:
Near the top of the file, you should see something like this:
... /** * Get port from environment and store in Express. */ var port = normalizePort(process.env.PORT || '3000'); app.set('port', port); ...
This tells us that our app will be running on port 3000, which is typically the standard. Now that we have this information, we can configure Nginx by creating a config file for our app:
Express is best served by Nginx via a reverse proxy, but don't worry about what that means: just make sure
server_name reflects your actual domain name, and that
proxy_pass contains the correct port number:
With that file saved, there are only two commands left to have Nginx fully set up. I'm not sure how much you care to learn about Nginx or understand what's actually happening below, but I'll assume most people don't:
$ sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/myapp.conf $ sudo service nginx restart
Nginx is now ready and pointing to your app! Your app isn't running yet though, so let's take care of that.
Run Your App
The most simple way to run your app immediately is by running
npm run start in your project folder, but this won't do the trick if we want a persistent application. Starting your app with
npm run start will only keep your app running as long as you're active in the terminal, as opposed to running it in the background forever. To keep your app running continuously, we'll use a tool called PM2:
$ npm install pm2 -g
PM2 allows you to run as many NodeJS apps as you want at once, and they won't end unless you force them to (or some fatal crash happens). Start your app with PM2:
$ pm2 start /var/www/myapp/bin/www
Your app should now be running and accessible on your server! To check which apps PM2 has running, enter
$ pm2 list:
┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐ │ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ ├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤ │ www │ 0 │ fork │ 8953 │ online │ 79 │ 35h │ 0% │ 44.6 MB │ root │ disabled │ │ www │ 1 │ fork │ 18195 │ online │ 0 │ 3D │ 0% │ 22.3 MB │ root │ disabled │ │ www │ 2 │ fork │ 19990 │ online │ 0 │ 33h │ 0% │ 49.2 MB │ root │ disabled │ └──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘
Congrats on setting up your first ExpressJS app! If you're new to this sort of thing, the next logical step for you would be to look into tools for preparing your code for production, such as grunt or webpack. Otherwise, you're good to go to serve static files directly out of the