Deploying Static and Node Applications with Zeit Now

This lesson has been adapted from Mykola Bilokonsky

Documentation can be found HERE

About Zeit Now

Up until now you've been running your projects from your own server on localhost. Now is a node package that lets you deploy static websites and node applications to a remote server, which allows anyone on the internet to visit your site. The free version allows you to deploy a limited number of sites, but it is perfect for showing potential employers your portfolio!

Now creates a deployment 'instance' every time you want to run a project on their server. This means a new unique domain name is generated each time you create or update a project.

*You can also deploy using a pre-purchased domain name, but that will be discussed in a later tutorial.

This tutorial goes over how to deploy the following:

  • Static HTML site (no server or database, just pure HTML/JS/CSS)
  • React app
  • React app with express.js server and mongoose

Installation

To install Now open your terminal and simply run this script in any directory:

npm install now -g

Deploying a Static HTML Site

When you are ready to deploy your static or node application, run this script:

now directory-of-your-project

or if you are already in your directory simply run:

now

When you first run now it will ask for your email to configure your account. This will require you to confirm the email sent to you.

If you are already logged in and have run now you should see your project being initialized and deployed. A url for your hosted app will be generated. Pretty simple, eh?

Here's a list of common now terminal commands:

  • now ls - shows the list of all current now instances in your account.
  • now rm <instance_id> - deletes an instance.
  • now alias <instance_url> <alias> - assigns a domain name which points to the provided now instance. Simply run it after you've deployed and

If you make any changes and deploy again it will create a new instance of your project and return a new unique URL. But wait, you don't want to have to change your website address every single time you update it! Plus, having a URL called www.my-website-3478jr87.now.sh isn't exactly memorable. The now alias command is what allows you to retain the desired domain name for your project.

Deploying a React App

Client-side only React App

If you are deploying a react app you will want to run the build script before deploying. You do this by running the command npm run build.

If your react app is only client side all you will need to do is run the command now in your build folder.

React app with Node Server

To make deploying simpler, make sure your main project folder looks something like this:

Basically all your backend files should be loose inside your main project folder.

Since we aren't going to be using the development server anymore we need to tell our express.js server to handle the React files.
After running the build script, you will want to go in your server file and add this code to serve your react app from your server:

const path = require("path");
//don't forget to npm install -s path

app.use(express.static(path.resolve(__dirname, "client", "build")));
app.get("/", (req, res) => {
  res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
}); 

The above code is just an example, and depending on where your server file and where your build folder is you may need to alter the path after __dirname to correct the path to your build folder.

You may also have been making http requests on your client side to somewhere like http://localhost:8080/api/todo, this will need to be changed to just /api/todo since your react app is running on your server now.

The last thing we need to do before deploying is tell now how to start our server. Add this to the scripts property in the package.json associated with your server:

...,
"scripts": {
    ...,
    "start": "node index.js",
}

When your application is configured and ready to be deployed just run now from the main project folder.

React App with Node server and mongoDB

So far we've been using mongoDB locally on our computer to store database collections. Since we are deploying an app that runs on a server somewhere else, we can't rely on localhost anymore. We will be using Mlab, which is a cloud database hosting service.

To begin, make sure to sign up for an account at mlab.com.

Once you're logged in click the create new + button under the MongoDB Deployments tab. Select the sandbox option and submit. Name your database whatever you like. You should see your new collection being added to your home page:

Clicking on it will take you to another page where you can view the URI. Click on the User tab and create a database user with a new username and password.

DO NOT USE YOUR MLAB LOGIN ACCOUNT INFO!!

Before we move on, take note of the URI at the top. We will be using this in a minute to connect to our remote database.

Configurations

So far our server is able to provide the index.html file located in the React build folder but is still connected to the mongoDB instance running on your localhost. If your project includes user auth then you probably also have a secret stored in a config.js file. You also have a port variable as well. We're going to store all these in what are called environment variables which now will have access to upon deployment.

From config.js:

module.exports = {
  port: process.env.PORT || 8000,
  secret: process.env.SECRET || "whatever your secret is",
  db: process.env.DB || "mongodb://localhost/class-demo"
}

From index.js:

const config = require("./config.js");

...
mongoose.connect(config.db, ()=>{
  console.log("connected to database");  
})

...
app.listen(config.port, ()=>{
  console.log("listening on " + config.port);
})

Don't forget to import your secret if you're using it in one of your routes!

In package.json from the project folder we'll make a now config object that has information about the specific deployment:

{
...,
"now": {
    "alias":"class-demo",
    "name": "class-demo",
    "env": {
      "PORT": 8000,
      "SECRET": "@secret", //if you have one
      "DB": "@db"
    }
  },
...,
}

Finally, we need to define the values of our environment variables. We can explicitly define the port number because it's public information. However, we don't want anyone to know the database URI or secret. We can define these in a secure way using the now secret command:

  • copy the URI that you saw on your Mlab database
  • In Terminal, from your main project folder:
    now secret add db <copy_URI_here>. Don't forget to replace the <username> and <password> placeholders with the actual database username and password (The DATABASE user and password, NOT your Mlab account user and password). Notice that the name of the secret here matches with what is defined in your package.json (e.g. "DB":@db);
  • If you have a secret, just type now secret add secret "whatever you want your secret to be".

You can view secrets by typing now secret ls.
Delete them using now secret rm <name_of_secret>.

Running deployment scripts

Now that everything is configured let's write a script that will deploy our app!

From package.json:

...,
"scripts": {
    ...,
    "start": "node index.js",
    "deploy": "now --public"
},
...

The process for deploying a full stack app goes like this:

  • From /client run npm run build
  • From project folder run npm run deploy.
  • After project is deployed, run now alias to give your website a readable domain name.

That's it!

Note: Now will only allow you a maximum of 1 GB free storage and 100 MB individual file size for the sandbox account. You can purchase an upgrade for more.

Coming Soon...
Managing Past Now Deployments