DEV Community

Cover image for How to Deploy Angular Universal to Vercel
Jonathan Gamble
Jonathan Gamble

Posted on • Updated on

How to Deploy Angular Universal to Vercel

After 176 commits, memorizing the Vercel docs, searching through the Nuxt, Sveltekit, Vercel, and Next GitHub packages, browsing stackoverflow, and pulling my hair out, I finally got this thing to work. Then I didn't; then I did; then I simplified it, I found problems, and I came to a general solution.

Thanks to this guy's overly complicated monorepo, I found the missing pieces. It was not easy.

Here is the final working example:

Vercel Solution

Solution

  1. Create a vercel.json file at the root of your Angular Universal project with YOUR_PROJECT_NAME:

vercel.json

{
  "version": 2,
  "public": true,
  "name": "test-universal",
  "rewrites": [
    { "source": "/(.*)", "destination": "/api" }
  ],
  "functions": {
    "api/index.js": {
      "includeFiles": "dist/YOUR_PROJECT_NAME/browser/**"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

All we are doing is pointing all requests to the api/ folder. You must also select which files to give your script access to with includeFiles.

2. Rename scripts.build to scripts.build-dev in package.json. Vercel runs npm run build automatically, with only access for the browser. We do not need that in this case.

3. Add scripts.vercel-build with the value npm run build:ssr. This is run specifically within the serverless function to give you access to all your files and scripts.

package.json

{
  "name": "test",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build-dev": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test",
    "dev:ssr": "ng run test:serve-ssr",
    "serve:ssr": "node dist/test/server/main.js",
    "build:ssr": "ng build && ng run test:server",
    "prerender": "ng run test:prerender",
    "vercel-build": "npm run build:ssr"
  },
...
Enter fullscreen mode Exit fullscreen mode

4. Create the file api/index.js. All scripts in the api directory are automatically used as serverless functions.

api/index.js

const server = require('../dist/YOUR_PROJECT_NAME/server/main');

module.exports = server.app();
Enter fullscreen mode Exit fullscreen mode

5. Push to GitHub. An existing Vercel project will automatically deploy, or you can click New Project, and select your GitHub Repository.

That's it!

This took me a week to do, and it is so simple.

Vercel Team, please add this to your existing templates!

Now, I can use Angular and Vercel with their CDN and Edge Functions. There is similar functionality in Google Cloud, just a pain to configure.

FWI - There is a plugin for Netlify if you prefer a different provider. Either way, Angular Universal is now available on all major servers.

Until next time...

J

Update: If you have the Service Worker enabled, it will look like it is only loading the static version. Disable cookies temporarily, and you can see it works as expected.

Note: I should also tell you Vercel's Serverless functions have a 50mb limit. If you have a giant app, this is not the best server. NextJS is built to use Vercel so that each page uses its own Serverless function. I suspect SvelteKit will follow this pattern now that Rich Harris is on board with Vercel. That being said, Svelte is a baby, and I personally hate React. Better use Cloud Run for bigger apps.

Discussion (1)

Collapse
leehodges profile image
Lee Hodges • Edited on

Thanks for this! I made a few changes to my setup so I'm not always running production environments when I want to hit say staging backend.

Strip out "vercel-build": "npm run build:ssr" from package.json
Update "build:ssr" to "ng build --configuration production && ng run project-name-here:server"

Create vercel.sh in your root directory of the project

if [[ $VERCEL_GIT_COMMIT_REF == "main" ]]; then
  echo "This is our production branch"
  npm run build:ssr
elif [[ $VERCEL_GIT_COMMIT_REF == "master" ]]; then
  echo "This is our production branch"
  npm run build:ssr
else
  echo "This is not our production branch"
  npm run build:staging-ssr
fi 
Enter fullscreen mode Exit fullscreen mode

The above is just looking at what branch is being deployed, if it's main/master build:ssr will run if its any other branch my staging-environment deployment script will run.

Settings on Vercel for the project add custom build command of sh vercel.sh
settings