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.
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 API key there, and forward the request to the actual API on aqicn.org.
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.
(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:
- 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.
- Put the frontend app to the hosting service.
- Put the backend app (function, actually) to the Serverless Functions service.
- 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.
I create a new project in Vercel and link with the project’s 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.
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
.
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.
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.
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.
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.
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.
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.
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.
Once I’m logged in, I run $ vc
to link the local project to a 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.
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!