How to Deploy Angular Universal to Vercel

Jonathan Gamble - Dec 28 '21 - - Dev Community

Update - Angular 17.2 - 3/2/24

While you still can't get Vercel Edge deployments to work until the nodejs dependencies problem is resolved, you can now deploy @angular/ssr to Vercel serverless functions with a few changes:

  1. Create api/index.js file: ```js

export default import('../dist/YOUR-PROJECT/server/server.mjs')
.then(module => module.app());

2\. Add `vercel.json` file:
```json


{
  "version": 2,
  "public": true,
  "name": "YOUR-PROJECT",
  "rewrites": [
    {
      "source": "/(.*)",
      "destination": "/api"
    }
  ],
  "functions": {
    "api/index.js": {
      "includeFiles": "dist/YOUR-PROJECT/**"
    }
  }
}


Enter fullscreen mode Exit fullscreen mode

3. Comment out run() in server.ts as you will be running the server on Vercel functions.

4. If you don't want prerendering:

  • Rename index.html to index1.html, and update the path in angular.json at projects.architect.build.index to src/index1.html.
  • Also set projects.architect.build.options.prerender to false. This will ensure your code is dynamically rendered.

That's it! Thanks to @mickl, @trongthuong96, and @wolfsoko for the updates in the comments for figuring all this out. I have simplified what you said.

Demo: https://angular-vercel-ssr.vercel.app/
GitHub: https://github.com/jdgamble555/angular-vercel-ssr

Angular Test Site


Original Post


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.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .