In this guide, you will go through all the steps needed to migrate your Netlify application to Vercel.
Before you can start the migration you need to create a project on Vercel. This Getting Started guide will instruct you on how to add your project to Vercel.
Once the setup is complete, you can start migrating your application settings.
To migrate your domains to Vercel, refer to the following documentation:
Vercel will automatically detect the framework and any necessary build settings. However, you may have custom settings in Netlify that you need to migrate. You need to find the settings which can be found in either the UI or your netlify.toml
file.
1. Netlify UI Build Settings
Open your project in Netlify and find the Site Settings
.
Select Build and Deploy
from the left navigation. The Build Settings
section includes the information Vercel needs to build and deploy your application.
The three fields that need to be copied to Vercel are:
- Base Directory
- Build Command
- Publish Directory
2. netlify.toml
File Build Settings
In your netlify.toml
file, the build settings will be signified by a [build]
table which lists all the currently configured options for each command.
Inside the netlify.toml
file you can set a custom command to ignore builds signified by the ignore
key.
[build] base = "project/" publish = "build-output/" command = "echo 'default context'" ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF"
Open your Vercel project and locate the Settings
tab.
Locate the section called Build and Development Settings
and fill in the Build Command and Output Directory sections.
There is a section below where you can enter the base directory if you are using a monorepo.
If you had an ignore
key set in the netlify.toml
, you can add that to your Vercel settings. Select Git
from the left navigation in Vercel and locate the Ignored Build Step
section where you can copy the command.
If you have environment variables configured in Netlify, those will need to be migrated to Vercel. These settings can be found in either the UI or your netlify.toml
file.
1. Netlify UI Environment Data
Open your project in Netlify and find the Site Settings
.
Select Build and Deploy
from the left navigation and locate the Environment
section. This includes all the environment variables needed to configure your project, make note of them all to copy to Vercel.
2. netlify.toml
File Environment Data
In your netlify.toml
file, each environment's variables are signified by a [context.ENVIRONMENT.environment]
table which lists all the currently configured values for the environment.
[context.staging.environment] NOT_PRIVATE_ITEM = "not so secret"[context.prod.environment] NOT_PRIVATE_ITEM = "really not so secret"
Open your Vercel project and locate the Settings tab.
From the left navigation, select Environment Variables
and paste your environment variables from Netlify. You can choose to configure them to only apply to any specific environment or any custom branch.
There are two ways currently to configure rewrites and redirects in Netlify:
- A plain text file called
_redirects
without a file extension to the publish directory of your site in Netlify - One or more
redirects
tables in your Netlify configuration filenetlify.toml
You will need to take note of all the redirects set up in Netlify to properly configure them in Vercel.
1. _redirects
File
In a _redirects
file, each rule must be listed on a separate line, with the original path followed by the new path or URL. The status code is optional and listed at the end. A 200 status code indicates a rewrite.
/home //blog/my-post.php /blog/my-post/news /blog/cats /dogs 200
2. netlify.toml
File Redirects Data
In a netlify.toml
file, each rule will be signified by a [[redirects]]
table which lists all the currently configured options for each redirect.
[[redirects]] from = "/old-path" to = "/new-path" status = 301
[[redirects]] from = "/search" to = "https://api.mysearch.com" status = 200
Once you have collected all the rewrites and redirects in your application you can start configuring them in Vercel. The method will depend on your application framework.
1. Next.js (next.config.js
) Redirects
Next.js has a built-in way to configure redirects in your application and that is the preferred way to set them up in your application as they have precedence over platform-level redirects.
For each redirect and rewrite you can use the redirects
and rewrites
keys in the next.config.js
file in your project.
module.exports = { async rewrites() { return [ { source: '/about', destination: '/', }, ]; }, async redirects() { return [ { source: '/about', destination: '/', permanent: true, }, ]; },};
2. Non-Next.js (vercel.json
) Redirects
When using a framework without a built-in way to configure redirects you can create a vercel.json
file in your project to set them up.
For each redirect and rewrite you can use the redirects
and rewrites
keys in the vercel.json
file in your project.
{ "redirects": [ { "source": "/me", "destination": "/profile.html" }, { "source": "/user", "destination": "/api/user", "permanent": false }, { "source": "/view-source", "destination": "https://github.com/vercel/vercel" }, { "source": "/:path((?!uk/).*)", "has": [ { "type": "header", "key": "x-vercel-ip-country", "value": "GB" } ], "destination": "/uk/:path*", "permanent": false } ], "rewrites": [ { "source": "/about", "destination": "/about-our-company.html" }, { "source": "/resize/:width/:height", "destination": "/api/sharp" }, { "source": "/proxy/:match*", "destination": "https://example.com/:match*" }, { "source": "/:path((?!uk/).*)", "has": [ { "type": "header", "key": "x-vercel-ip-country", "value": "GB" } ], "destination": "/uk/:path*" } ]}
There are two ways currently to configure custom headers in Netlify:
- A plain text file called
_headers
without a file extension to the publish directory of your site in Netlify - One or more
[[headers]]
tables in your Netlify configuration filenetlify.toml
You will need to take note of all the headers set up in Netlify to properly configure them in Vercel.
1. _headers
File
In a _headers
file, you can specify one or several URL paths with their additional headers indented below them:
# a path:/templates/index.html # headers for that path: X-Frame-Options: DENY X-XSS-Protection: 1; mode=block# another path:/templates/index2.html # headers for that path: X-Frame-Options: SAMEORIGIN/* X-Frame-Options: DENY X-XSS-Protection: 1; mode=block
2. netlify.toml
File Headers Data
In a netlify.toml
file, each rule will be signified by a [[headers]]
table which lists all the currently configured options for each route.
[[headers]] for = "/*" [headers.values] X-Frame-Options = "DENY" X-XSS-Protection = "1; mode=block"
Once you have collected all the custom headers in your application you can start configuring them in Vercel. The method will depend on your application framework.
Next.js has a built-in way to configure custom headers in your application and that is the preferred way to set them up in your application as they have precedence over platform-level configuration.
1. Next.js (next.config.js
) Headers
For each custom header you can use the headers
keys in the next.config.js
file in your project.
module.exports = { async headers() { return [ { source: '/about', headers: [ { key: 'x-custom-header', value: 'my custom header value', }, { key: 'x-another-custom-header', value: 'my other custom header value', }, ], }, ]; },};
2. Non-Next.js (vercel.json
) Headers
When using a framework without a built-in way to configure headers you can create a vercel.json
file in your project to set them up.
For each header you can use the headers
key in the vercel.json
file in your project.
{ "headers": [ { "source": "/service-worker.js", "headers": [ { "key": "Cache-Control", "value": "public, max-age=0, must-revalidate" } ] }, { "source": "/(.*)", "headers": [ { "key": "X-Content-Type-Options", "value": "nosniff" }, { "key": "X-Frame-Options", "value": "DENY" }, { "key": "X-XSS-Protection", "value": "1; mode=block" } ] }, { "source": "/:path*", "has": [ { "type": "query", "key": "authorized" } ], "headers": [ { "key": "x-authorized", "value": "true" } ] } ]}
If using serverless functions outside of a framework like Next.js there will be a couple of steps involved to migrate them from Netlify to Vercel.
Netlify has a similar file-based routing system for their Serverless Functions where they are placed in a folder called functions/
, as opposed to api/
.
To run them on Vercel, they are expected to be found in a directory called api/
.
The function signatures between Netlify and Vercel Functions are also different and will require some modification.
Netlify uses an event
and context
input that matches AWS Lambda functions. A TypeScript Netlify function will look like this:
import { Handler } from '@netlify/functions';
const handler: Handler = async (event, context) => { return { statusCode: 200, body: JSON.stringify({ message: 'Hello World' }), };};
export { handler };
Vercel uses a standard Request
and Response
API:
export function GET(request: Request) { return new Response(`Hello from ${process.env.VERCEL_REGION}`);}
If using middleware outside of a framework like Next.js there will be a couple of steps involved to migrate them from Netlify to Vercel.
Netlify's Middleware structure differs from Vercel's file-based routing system. They are currently placed in a folder called netlify/edge-functions
and require configuration in the netlify.toml
file to match specific routes.
[[edge_functions]]path = "/test"function = "hello"
To use Middleware on Vercel, they are expected to be found in a single file called middleware.ts
at the root of your project.
The function signatures between Netlify and Vercel functions are also different and will require some modification.
Netlify uses a request
and context
input which matches the underlying Deno functions. A TypeScript Netlify function will look like this:
import type { Context } from 'https://edge.netlify.com';
export default async (request: Request, context: Context) => { return context.rewrite('/about-2');};
Vercel uses a standard Request
input object and also requires a config object to match the middleware to specific routes:
import { rewrite } from '@vercel/edge';
export function middleware(request: Request) { return rewrite(new URL('/about-2', request.url));}// config with a custom matcherexport const config = { matcher: '/test',};