DEV Community

Cover image for How to Deploy Angular Universal to Vercel

How to Deploy Angular Universal to Vercel

Jonathan Gamble on December 28, 2021

Update - Angular 17.2 - 3/2/24 While you still can't get Vercel Edge deployments to work until the nodejs dependencies problem is resol...
Collapse
 
mickl profile image
Mick

Hey! Did you try it out with the new Angular 17 yet? They added integrated SSR support to Angular. Now running "ng serve" or "ng build" automatically starts SSR server, thats awesome!

Anyway, Vercel now throws the error:

Cannot find module '../dist/server/main'

The server folder looks way different now and has .mjs modules instead of .js.

Angular 16:
Image description

Angular 17:
Image description

Collapse
 
jdgamble555 profile image
Jonathan Gamble • Edited

Try with this on the import file:

const server = require('../dist/angular-vercel/server/server');

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

And just keep all the package.json the same without editing it.

J

Collapse
 
mickl profile image
Mick • Edited

Ahhhh I totally forgot about the api/index.js and was wondering here he gets this server/main from ... :) Anyway I could NOT get it to work yet! I tried to all different kind of imports and renaming the file from index.js to index.mjs but I couldnt find the correct way yet. Maybe you have a look at it?

import server from '../dist/angular-vercel/server/server';

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

OR

import app from '../dist/server/server.mjs';

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

Nothing works...

Btw the package.json is now significantly different! Thats because ng build already builds browser and server app, so no more need for build:ssr! This also means build/deploy time went from 2 minutes to 1 minute :)

Thread Thread
 
jdgamble555 profile image
Jonathan Gamble

You have to use require because it is JS. Did you try my code? You're importing 'server.mjs'... hence server/server.

Thread Thread
 
mickl profile image
Mick

I think thats the first thing tried but in mjs there is no require allowed anymore when I remember correct. I renamed index.js to index.mjs because it was not working.

Thread Thread
 
jdgamble555 profile image
Jonathan Gamble
Collapse
 
leehodges profile image
Lee Hodges • Edited

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

Collapse
 
amaurygoncalves profile image
Amaury Gonçalves Costa • Edited

Thanks man for this!! It has saved me, rsss. Thanks 4 share!

Collapse
 
mickl profile image
Mick

Thanks a lot for the article! Does this also work with Vercel Edge Runtime, which is just a subset of the Node API?

Collapse
 
jdgamble555 profile image
Jonathan Gamble • Edited

I have not tested it, but there is no reason it shouldn't work on the edge, as it is just JavaScript. You can try adding this to the index.js:

export const config = {
  runtime: 'edge',
};
Enter fullscreen mode Exit fullscreen mode

vercel.com/docs/edge-network/caching

Let me know if you figure it out!

J

Collapse
 
mickl profile image
Mick • Edited

It would require to also set the response header as written in the docs BUT I tried it out and it doesnt work:

Error: The Edge Function "api/index" is referencing unsupported modules:

  • dist/server/main.js: crypto, fs, http, https, net, os, path, querystring, stream, string_decoder, timers, tty, url, zlib, node:fs, node:path

There is an open feature request to remove the dependencies of Angular Universal (e.g. remove Express) so it can work on workers that dont support full Node API like Vercel Edge Functions or Cloudflare Pages BUT it will probably be closed if it doesnt get 20 upvotes in the next week:

github.com/angular/angular-cli/iss...

Thread Thread
 
jdgamble555 profile image
Jonathan Gamble • Edited

Yup, I just tried it and go the same error. Normally in Node.js, you could use the "browser" key in package.json to ignore certain imports, but the edge uses Deno. Until this gets resolved (I upvoted BTW), I don't see Angular Universal being possible on Vercel or any Edge. However, AnalogJS may be a different thing.

Thread Thread
 
mickl profile image
Mick

Did you find anything out in the meantime?

Thread Thread
 
mickl profile image
Mick

I got it working thangs to @trongthuong96 ! I posted it on top level

Collapse
 
tobias_michelchen profile image
Tobias Michelchen

calling here from 2025... guide helped me a lot getting ssr@vercel running. With Angular 19 the angular team changed the structure of server.ts a little. So a little additional changes are necessary.

First you will need to export app-constant in server.ts

export const app = express();

2nd you just need to export "app" instead of calling the "app()" which was previously a function creating the express server. Paste this in api/index.js to get ready.

export default import('../dist/angular-vercel-ssr/server/server.mjs').then(module => module.app);

With those to changes + added vercel.json everything works with Angular 19.

Collapse
 
cxxyao2 profile image
cxxyao2

Thank you ! I deployed Anguar 19 ssr successfully according to your guide.

Collapse
 
duxor profile image
duXor

Spent hours debugging Angular 19+ SSR on Vercel and finally got it working (also tested on Angular 20 RC).

Here's the full guide with steps and code:
Angular SSR on Vercel

Collapse
 
cotentin profile image
Corentin

Hi, I'm trying to push my Angular app (v16.2) to Vercel with SSR. I followed the steps and the deployment works fine. However, when I inspect the page source, I only see an <app-root> tag with nothing inside, indicating that the site isn't rendered server-side. I'm having trouble understanding why this is happening.

Collapse
 
jdgamble555 profile image
Jonathan Gamble

Did you follow the index renaming and prerendering off part as well? I have also only tested on Angular 17.

Collapse
 
keval101 profile image
Keval Vadhiya • Edited

Just an update:

I have tried with Angular19
We don't need vercel.json and api folder with index.js
I didn't change anything with angular

on Vercel configuration I just changed the deployment command to

node dist/project_name/server/server.mjs
Enter fullscreen mode Exit fullscreen mode

Image description

Collapse
 
panesarpbx8 profile image
Sukhpreet Singh

Thanks for sharing this man! this is helpful

but one problem I am facing is my app is not server-rendered.

the home url is working but only the static version (with cookies disabled)
but any other url is taking more than 10 seconds to respond, resulting in 504 function timeout error.

could you please help my out?
Thanks

Collapse
 
jdgamble555 profile image
Jonathan Gamble

You may have a loop in your code. Make sure to test it with npm run dev:ssr first. Usually it is a login code that should only be ran on the frontend.

Collapse
 
georgeknap profile image
George Knap

why is your functions pointing to dist/YOUR_PROJECT_NAME/browser/** ?
Shouldn't it be from .../server/**?

Collapse
 
jdgamble555 profile image
Jonathan Gamble

No, the server is the index.js file. That is for the static files like images, css, etc

Collapse
 
meabhinavakhil profile image
Abhinav • Edited

Hey, this is my configuration but i am getting errors as show below.

Image description

api/index.js

Image description

vercel.json

Image description

package.json

Image description

Image description

using Angular V17

Please let me know on how to fix this. Thanks

Collapse
 
leonardo_pradovargasda profile image
leonardo prado vargas da gama

Wow, nice tutorial, you save me! 🙏

Collapse
 
mickl profile image
Mick • Edited

Thanks for the article!! One little thing: Instead of step 2 and 3 you could just go to the Vercel website and tell it to run "npm run build:ssr" or "yarn build:ssr".

Collapse
 
jdgamble555 profile image
Jonathan Gamble

Well you have to have the Vercel config file anyway, so this actually skips that step.

Collapse
 
abdelkader-k profile image
Klalib

Thanks for this, How can i used with i18n ?

Collapse
 
jdgamble555 profile image
Jonathan Gamble

Not sure about that, never used i18n on any framework. Post here if you figure it out!

Collapse
 
hieutranagi47 profile image
Hieu Tran

I do like this:
api/en/index.js

export default import('../../dist/langs/server/en/server.mjs')
  .then(module => module.app());
Enter fullscreen mode Exit fullscreen mode

api/vi/index.js

export default import('../../dist/langs/server/vi/server.mjs')
  .then(module => module.app());
Enter fullscreen mode Exit fullscreen mode

vercel.json:

{
    "version": 2,
    "public": true,
    "name": "langs",
    "rewrites": [
      {
        "source": "/vi/(.*)",
        "destination": "/api/vi"
      },
      {
        "source": "/en/(.*)",
        "destination": "/api/en"
      }
    ],
    "functions": {
      "api/en/index.js": {
        "includeFiles": "dist/langs/en/**"
      },
      "api/vi/index.js": {
        "includeFiles": "dist/langs/vi/**"
      }
    },
    "redirects": [
      { "source": "/", "destination": "/en", "permanent": false }
    ]
  }
Enter fullscreen mode Exit fullscreen mode

And angular.json

"projects": {
    "langs": {
      ...
      "i18n": {
        "locales": {
          "vi": {
            "translation": "src/locales/messages.vi.xlf",
            "baseHref": "/vi/"
          },
          "en": {
            "translation": "src/locales/messages.xlf",
            "baseHref": "/en/"
          }
        }
      }
...
  }
}
Enter fullscreen mode Exit fullscreen mode

I don't know how to make it work with the default language (en) to use "baseHref": "/"

Collapse
 
anupam96786 profile image
Anupam Samanta

Using angular 17 ssr. This guide helped me a lot. Thank you.

Collapse
 
francdore profile image
Francois La Cock

Thank you!! That worked like a charm after I got 404 not found errors on Vercel.