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 currentnow
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
runnpm 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