Migrating a Nuxt SSR App from Heroku to Vercel
Tags: nuxt, vercel, heroku, ssr
Published: 2023-01-03 01:27:26

As of December 2022, Heroku has transitioned to a paid plan for hosting server-side apps. This left myself and many others with broken apps, with the option to pay for ‘dynos’ to get our apps running or migrate. If you’re like me and used Heroku for personal use, you probably don’t want to switch to a paid plan for fear of fluctuating hosting expenses and are going to look into alternatives. Most popular hosting services we know of (Netlify, Vercel, Firebase) have out-of-the-box support for static apps but require a bit more involvement when it comes to server-side rendering. Hence, I put together this guide for the very specific use case of apps built with Nuxt 2. I also have a Troubleshooting section for issues I faced that others might run into.

## Step 1 - Create a Vercel account

Go to https://vercel.com to create a free account.

## Step 2 - Configure your project for Vercel

Vercel supports non-SSR out of the box, but for SSR to work, we need to deploy a serverless function that handles all the server-related functions. For this, we will need to use https://github.com/nuxt/vercel-builder built by the Nuxt community. To use it you need to create a `vercel.json` in your project’s root directory. 

```jsx
{
  "version": 2,
  "builds": [
    {
      "src": "nuxt.config.js",
      "use": "@nuxtjs/vercel-builder"
    }
  ]
}
```

## Step 3 - Create a new project by importing your repository

![Import project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f4lhergctve1q0cvpv0e.png)

## Step 4 - Copy over necessary environment variables from Heroku to Vercel

![Environment variables](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zjsx0hjm4bo244q112bu.png)

## Step 5 - Fill in the deployment settings

![Settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zoikxar28104mv9b4lrp.png)

Choose Nuxt.js as the framework preset and fill in the build commands. The default commands should work but I added the yarn commands just to be sure. The commands are run in the following order.

1. `yarn install` will grab all of the dependencies needed for your app to run
2. `yarn generate` will compile your client-side and server-side code and package it into minified files that will be saved in your output directory (`dist`)
3. `yarn start` starts the process that will run your app.

These steps are identical to those needed to run your app locally. 

## Step 6 - Deploy

I was able to migrate my SSR Nuxt.js application from Heroku to Vercel with these steps. If you’re still having issues, look through the troubleshooting section below or reach out to me. For reference, here is the code for my application - https://github.com/gucci-ninja/dotboard which is now running on [https://dotboard.vercel.app/](https://dotboard.vercel.app/). Thanks!

## Troubleshooting

### Error - This serverless function has crashed/No build files found

![Server error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bqaf14o751ppfplv84g8.png)

```jsx
FATAL  No build files found in /var/task/.nuxt/dist/server.
Use either `nuxt build` or `builder.build()` or start nuxt in development mode.
Use either `nuxt build` or `builder.build()` or start nuxt in development mode.
at VueRenderer._ready (node_modules/@nuxt/vue-renderer/dist/vue-renderer.js:4204:13)
at async Server.ready (node_modules/@nuxt/server/dist/server.js:615:5)
at async Nuxt._init (node_modules/@nuxt/core/dist/core.js:703:7)
2023-01-03T00:01:47.485Z	undefined	ERROR	λ Error while initializing nuxt: Error: No build files found in /var/task/.nuxt/dist/server.
Use either `nuxt build` or `builder.build()` or start nuxt in development mode.
    at VueRenderer._ready (/var/task/node_modules/@nuxt/vue-renderer/dist/vue-renderer.js:4204:13)
    at async Server.ready (/var/task/node_modules/@nuxt/server/dist/server.js:615:5)
    at async Nuxt._init (/var/task/node_modules/@nuxt/core/dist/core.js:703:7)
RequestId: 9f4fdef5-a109-4497-95e9-5f5c8f2a905b Error: Runtime exited with error: exit status 1
Runtime.ExitError
```

**Solution**

Version lock vercel-builder to `0.23.0` as there is an issue with `0.24.0` not invoking the serverless function.

```jsx
{
  "version": 2,
  "builds": [
    {
      "src": "nuxt.config.js",
      "use": "@nuxtjs/vercel-builder@0.23.0"
    }
  ]
}
```

**Relevant links**

- [https://github.com/nuxt/vercel-builder/issues/765#issuecomment-1358290407](https://github.com/nuxt/vercel-builder/issues/765#issuecomment-1358290407)

### Error - Outdated dependencies

If you’re like me and were not actively developing your app, some of the dependencies might be outdated or need to be upgraded. So a quick test is to run the app locally and see if everything is working as expected. For example, I was getting the following error.

```jsx
make: Entering directory `/vercel/path0/node_modules/node-sass/build'

gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2

Build failed with error code: 1
Error: Command "yarn install" exited with 1
```

**Solution**

I removed `node-sass` from my dependencies as I was not using it. I also needed to downgrade my `sass-loader` from `^9.0.3` to `^7.1.0`

**Relevant links**

- [https://stackoverflow.com/questions/60394291/error-node-modules-node-sass-command-failed](https://stackoverflow.com/questions/60394291/error-node-modules-node-sass-command-failed)
- [https://stackoverflow.com/questions/58623072/npm-node-sass-installation-fails](https://stackoverflow.com/questions/58623072/npm-node-sass-installation-fails)

### Error - 404 when calling API. Runtime logs on Vercel showing 404 as the response status

**Solution**

If you have any endpoints or routes in your server code, you need to declare them in the `vercel.json`. I have a `server/` folder which holds all the endpoints that my app serves (`/api/auth/login`, `/api/auth/user`) The code to handle all these requests resides in `/server/index.js`. 

```jsx
{
  "builds": [
    {
        "src": "server/**/*.js", // path to code that handles API requests
        "use": "@vercel/node"
    },
    {
      "src": "nuxt.config.js",
      "use": "@nuxtjs/vercel-builder@0.23.0",
      "config": {}
    }
  ],
  "routes": [
    {
      "src": "/api/auth/login", // endpoint 1
      "dest": "/server/index.js" // code that handles endpoint 1
    },
    {
      "src": "/api/auth/user", // endpoint 2
      "dest": "/server/index.js" // code that handles endpoint 2
    }
  ]
}
```

**Relevant links**

- [https://github.com/nuxt/vercel-builder/blob/main/examples/basic/vercel.json](https://github.com/nuxt/vercel-builder/blob/main/examples/basic/vercel.json)

### Error - Deployment hanging and taking 7+ minutes

```jsx
NowBuildError: node_modules_prod/rxjs/src/internal/observable/from.ts(116,5): error TS2322: Type 'import("/vercel/path0/node_modules/rxjs/internal/Observable").Observable<T>' is not assignable to type 'import("/vercel/path0/node_modules_prod/rxjs/src/internal/Observable").Observable<T>'.
node_modules_prod/rxjs/src/internal/observable/from.ts(116,29): error TS2345: Argument of type 'import("/vercel/path0/node_modules_prod/rxjs/src/internal/types").SchedulerLike' is not assignable to parameter of type 'import("/vercel/path0/node_modules/rxjs/internal/types").SchedulerLike'.
node_modules_prod/rxjs/src/internal/scheduled/scheduled.ts(31,38): error TS2345: Argument of type 'import("/vercel/path0/node_modules/rxjs/internal/types").SchedulerLike' is not assignable to parameter of type 'import("/vercel/path0/node_modules_prod/rxjs/src/internal/types").SchedulerLike'.
```

**Solution**

Not sure what the issue was but retrying the deployment worked.