Moving an App to Vercel

I migrated my app cmair.space from DigitalOcean server to Vercel (formerly ZEIT Now). This is a note on my experiences and what I have learned.

About the app

Back in 2017, I built a pet project called cmair.space to display the AQI value near where I live using data from aqicn.org.

The app is a one-page HTML with some JavaScript. It pulls the JSON data from an API endpoint and updates the UI based on the retrieved values. In this case, the number and page background color.

screenshot of cmair.space
cmair.space screenshot on a classic iPhone 6 frame

aqicn.org provides a free API. And like other APIs, it requires an API key to send along with the request.

I built my API on the server side to keep my there API key and forward the request to the actual API on aqicn.org.

data-flow

I wanted to keep everything in the same place so I put both frontend and backend parts in Express.js (a node web framework). Host it on my DigitalOcean droplet.

Automated deployment was set up kind of manually too. I used github-webhook-handler to add another route /pull to Express and use it with GitHub webhooks.

Whenever I push the code to GitHub, it’ll ping the route. The route callback then pulls the code from github, and restart the Express app on the server which is managed by pm2.

It was not a lot to set up, but at that time I also thought it should be easier. As a frontend developer, I always want to focus on the frontend side where the application logic is, and wish to do less on the server side.

Going Serverless

I have been hearing ‘serverless’ buzzword but never have a chance to use it.

It could be a great fit for my little serverful app if I can host the frontend part statically and connect to my API which is on this serverless magic thing.

Vercel is a cloud platform for static sites and serverless functions. I see Vercel as a direct competitor to Netlify. I’m using Netlify already with this blog and am impressed by how Netlify makes many things a lot easier. I’m curious how it compares to Vercel so I give Vercel a try this time.

vercel homepage
Vercel.com home page

(I tried AWS Lambda a while ago and didn’t get it much. It is too complicated for me as a frontend developer.)

Moving Process

My rough plan would be:

  1. Take frontend app and backend part out of Express. This is relatively easy because in the app there is not much to do with Express anyway.
  2. Put the frontend app to the hosting service.
  3. Put the backend app (function, actually) to the Serverless Functions service.
  4. Make the domain cmair.space point to Vercel.

Deploy the frontend app to the hosting service

When signing up on Vercel with my GitHub account, it installs ‘Now’ app on Github.

Now GitHub app

I create a new project in Vercel and link with the project’s repo.

importing a project from github
select a github repo

Vercel tries to guess what framework I’m using. Express is not on the list, but Vercel can still deploy correctly from public/ directory. There is no build command.

set project framework and build command

Now the frontend part is deployed. At this point, it is not working because there is no API backend for it yet.

Put the backend function to Serverless Functions

I follow the official docs on Serverless Functions with some examples from jamstackfns.

Vercel’s Serverless Functions support TypeScript out of the box 💪. No build tools needed. The only thing I have to do is install add TypeScript as a dependency.

$ npm install -D typescript

I create a new branch called now (always create a branch if you know you can mess up things).

Then create a new file api/get-aqi.ts. This will make the endpoint available at /api/get-aqi.

Then I go to project settings in Vercel. Under General » Environment Variables, I create a new environment variable for my API key called TOKEN.

Environment variable in project settings

Then I can use this environment variable with process.env.TOKEN in my Serverless Function code.

There are 3 environments: Production, Preview, and Development. Since I created a new branch off the master branch, it will use the Preview environment when I deploy my branch to Vercel.

I finish the function. Then I push the branch to GitHub and create a pull request. Vercel creates a build and deploys to the Preview environment.

Vercel integration on GitHub's pull request

When I push more commits to the PR, Vercel creates a new preview URL for each push. I can click View deployment buttons to view the previews.

Vercel creates a new URL for previews

Now my API endpoint is up on Serverless Functions. So I have to update the API endpoint URL in my frontend app to point to the new URL.

-   const url = `/api`;
+   const url = `/api/get-aqi`;

And my app is now running on Vercel.

There is a page to see the logs from the serverless function in Vercel dashboard.

Serverless Functions info on Vercel Dashboard

Update Custom Domain

Similar to Netlify, Vercel also provides using custom domains for apps on Vercel with HTTPs for free. A benefit here for me is I don’t have to manage Let’s Encrypt certificates on the server for the domain anymore. It is one less thing to do.

I update DNS settings of my domain cmair.space to point to Vercel’s DNS server.

Set custom DNS to Vercel's DNS server

Then in Vercel Dashboard: I go to Project Settings » Domain and add a custom domain. Vercel displays the status while the DNS servers are updating, and also show the status once they are successfully updated.

Set custom domain in Vercel

And now my app is successfully migrated to Vercel 🎉🎉.


Vercel CLI

So far I have it all set up on Vercel, but I found the development process not very fun: every time I update the serverless function, I have to push to GitHub and wait for Vercel to deploy to the preview branch to see the changes. Debugging is also difficult to do in the remote environment.

Then I found they also have Vercel CLI to help with local development.

Vercel CLI home page

I install it globally. The commands available are vercel or vc in short. (the command now changes to vercel since version 19 of the CLI)

$ npm install -g vercel

First I have to login

$ vc login

Vercel asks for the email for my account and sends a magic link to the email. Click on the link and I’m logged in.

Vercel CLI Login

Once I’m logged in, I run $ vc to link the local project to a project on Vercel.

link the local project to the project on vercel

Before being able to run the dev server, I need to have the TOKEN environment variable available locally. I can do this by

$ vc env pull

This downloads the environment variables of DEVELOPMENT environment and puts them in .env file in the project. This is very convenient as I don’t have to create and manage the .env files myself manually.

I can run the local dev server with

$ vc dev

And I have both frontend app and serverless functions run locally. Making local development and debugging much easier.

running local dev server

Note: Netlify also has something similar called Netlify Dev.

The Difference in Deploy Previews

One difference on the deploy previews feature between Vercel and Netlify is: Vercel creates a deploy preview environment on a new push (e.g. new commit or new branch), while on Netlify, we have to create a Pull Request on GitHub to create a preview build.


Summary

Overall, my development experience with Vercel has been great. Even though my pet project is pretty simple, I have learned quite a lot about serverless and Vercel as a platform.

Local development experience with Vercel CLI is also a big plus. I can run and debug my serverless function locally and it works the same as on the cloud.

A small pet project like this cannot utilize the maximum capabilities of the serverless platform. Building a full-featured application would require a lot more. At least I can see how it works and how I can do things a little differently for my next app, if it needs to have some sort of server-side functionality.

I recommend trying out Vercel. It’s free for personal use. Check out examples on GitHub for more framework-specific examples.


P.S. cmair.space is actually my last project on my DigitalOcean droplet. Now I don't need to have my own server anymore. Hammergeil!

destroying DigitalOcean droplet

Related Posts