Nuxt on Vercel
Learn how to use Vercel's features with Nuxt.Nuxt is an open-source framework that streamlines the process of creating modern Vue apps. It offers server-side rendering, SEO features, automatic code splitting, prerendering, and more out of the box. It also has an extensive catalog of community-built modules, which allow you to integrate popular tools with your projects.
You can deploy Nuxt static and server-side rendered sites on Vercel with no configuration required.
There are multiple ways to get started with Nuxt on Vercel:
- If you already have a project with Nuxt, install Vercel CLI and run the
vercel
command from your project's root directory - Clone one of our Nuxt example repos to your favorite git provider and deploy it on Vercel with the button below:
- Or, choose a template from Vercel's marketplace:
Vercel deployments can integrate with your git provider to generate preview URLs for each pull request you make to your Nuxt project.
You can configure your Nuxt deployment by creating a Nuxt config file in your project's root directory. It can be a TypeScript, JavaScript, or MJS file, but the Nuxt team recommends using TypeScript. Using TypeScript will allow your editor to suggest the correct names for configuration options, which can help mitigate typos.
The following is an example of a Nuxt config file with no options defined:
export default defineNuxtConfig({
// Config options here
});
Your Nuxt config file should export defineNuxtConfig
by default, which you can add an options object to.
See the Nuxt Configuration Reference docs for a list of available options.
When using Nuxt with Vercel, you'll get the most value out of the routeRules
option, which allows you to configure how routes are deployed. At the moment, there is no way to configure route deployment options within your page components, but development of this feature is in progress.
The following is an example of a Nuxt config that handles redirects, header modifications, and activating client-side rendering for a group of specified routes:
export default defineNuxtConfig({
routeRules: {
'/examples/*': { redirect: '/redirect-route' },
'/modify-headers-route': { headers: { 'x-magic-of': 'nuxt and vercel' } },
'/spa': { ssr: false },
},
});
To learn more about routeRules
:
- Read Nuxt's reference docs to learn more about the available route options
- Read the Nitro Engine's Cache API docs to learn about cacheing individual routes
Edge Functions are a fast, scalable solution for delivering dynamic content to users. By default, Edge Functions are deployed globally, and will be invoked in one of Vercel's Edge regions near your site's visitors.
Edge Functions are ideal when you need to interact with data over the network as fast as possible, such as executing OAuth callbacks, responding to webhook requests, or interacting with an API that fails if a request is not completed within a short time limit.
When you deploy Nuxt projects with Edge Functions, Nuxt will directly render your routes in CDN edge workers, reducing latency and costs. Every API and middleware route will be executed on the Edge. They will also be bundled into a single Edge Function handler.
To use Edge Functions with Nuxt on Vercel, you must add a NITRO_PRESET
environment variable to your project and set its value to vercel-edge
. Doing so will cause your SSR routes to be deployed with Edge Functions.
You can set environment variables in your project's dashboard on Vercel under Settings ➞ Environment Variables.
See our docs on declaring environment variables to learn more.
See our Function comparison table to understand whether Edge or Serverless is best for your use-case.
To summarize, Edge Functions with Nuxt on Vercel:
- Offer cost savings by using fewer resources than Serverless Functions
- Can execute in the region nearest to your users or nearest to data sources they depend on, based on your configuration
- Have access to the geolocation and IP address of visitors, enabling location-based personalization
Learn more about Edge Functions
Serverless Functions enable developers to write functions that uses resources that scale up and down based on traffic demands. This prevents them from failing during peak hours, but keeps them from running up high costs during periods of low activity.
Nuxt deploys routes defined in /server/api
, /server/routes
, and /server/middleware
as one server-rendered Serverless Function by default when you deploy using nuxt build
.
All API and middleware routes will be bundled into a single Serverless Function to reduce cold starts, ensuring faster responses to requests in most cases. When a request to a serverless route is made, this function dynamically imports only the code needed to render the route requested.
See our Edge Functions section to learn how to deploy your routes as Edge Functions instead.
The following is an example of a basic Serverless API route in Nuxt:
export default defineEventHandler(() => 'Hello World!');
You can test your serverless routes with nuxt dev
.
See our Function comparison table to understand whether Edge or Serverless is best for your use-case.
To summarize, Serverless Functions on Vercel:
- Scale up and down to match user demand without reducing your app's performance or crashing
- Support standard Web APIs, such as
URLPattern
,Response
, and more - Are bundled into a single route, improving latency by reducing cold starts
Learn more about Serverless Functions
Middleware is code that executes before a request is processed. Because Middleware runs before the cache, it's an effective way of providing personalization to statically generated content.
Nuxt has two forms of Middleware:
In Nuxt, modules defined in /server/middleware
will be deployed as server middleware. Server middleware should not have a return statement or send a response to the request.
Server middleware is best used to read data from or add data to a request's context
. Doing so allows you to handle authentication or check a request's params, headers, url, and more.
The following example demonstrates Middleware that:
- Checks for a cookie
- Tries to fetch user data from a database based on the request
- Adds the user's data and the cookie data to the request's context
import { getUserFromDBbyCookie } from 'some-orm-package';
export default defineEventHandler(async (event) => {
// The getCookie method is available to all
// Nuxt routes by default. No need to import.
const token = getCookie(event, 'session_token');
// getUserFromDBbyCookie is a placeholder
// made up for this example. You can fetch
// data from wherever you want here
const { user } = await getUserFromDBbyCookie(event.request);
if (user) {
event.context.user = user;
event.context.session_token = token;
}
});
You could then access that data in a page on the frontend with the useRequestEvent
hook. This hook is only available in routes deployed with SSR. If your page is rendered in the browser, useRequestEvent
will return undefined
.
The following example demonstrates a page fetching data with useRequestEvent
:
<script>
const event = useRequestEvent();
const user = ref(event.context?.user);
</script>
<template>
<div v-if="user">
<h1>Hello, {{ user.name }}!</h1>
</div>
<div v-else>
<p>Authentication failed!</p>
</div>
</template>
Nuxt's route middleware runs before navigating to a particular route. While server middleware runs in Nuxt's Nitro engine, route middleware runs in Vue.
Route middleware is best used when you want to do things that server middleware can't, such as redirecting users, or preventing them from navigating to a route.
The following example demonstrates route middleware that redirects users to a secret route:
export default defineNuxtRouteMiddleware((to) => {
console.log(
`Heading to ${to.path} - but I think we should go somewhere else...`,
);
return navigateTo('/secret');
});
By default, route middleware code will only run on pages that specify them. To do so, within the <script>
tag for a page, you must call the definePageMeta
method, passing an object with middleware: 'middleware-filename'
set as an option.
The following example demonstrates a page that runs the above redirect middleware:
<script>
definePageMeta({
middleware: 'redirect'
})
</script>
<template>
<div>
You should never see this page
</div>
</template>
To make a middleware global, add the .global
suffix before the file extension. The following is an example of a basic global middleware file:
export default defineNuxtRouteMiddleware(() => {
console.log('running global middleware');
});
See a detailed example of route middleware in Nuxt's Middleware example docs.
To summarize, Middleware with Nuxt on Vercel enables you to:
- Redirect users, and prevent navigation to routes
- Run authentication checks on the server, and pass results to the frontend
- Scope middleware to specific routes, or run it on all routes
Server-Side Rendering (SSR) allows you to render pages dynamically on the server. This is useful for pages where the rendered data needs to be unique on every request. For example, checking authentication or looking at the location of an incoming request.
Nuxt allows you to deploy your projects with a strategy called Universal Rendering. In concrete terms, this allows you to deploy your routes with SSR by default and opt specific routes out in your Nuxt config.
When you deploy your app with Universal Rendering, it's rendered on the server once, then your client-side JavaScript code is interpreted in the browser again once the page loads.
On Vercel, Nuxt apps are server-rendered by default when you build with nuxt build
. You can opt routes out of this behavior by using routeRules
and setting the ssr
option to false
as demonstrated below:
export default defineNuxtConfig({
routeRules: {
// Use client-side rendering for all routes
'/**': { ssr: false },
},
});
Setting ssr: false
for routes will cause them to deploy with client-side rendering.
To deploy a static site, build your project with nuxt generate
.
To summarize, SSR with Nuxt on Vercel:
- Scales to zero when not in use
- Scales automatically with traffic increases
- Allows you to opt individual routes out of SSR with your Nuxt config
Incremental Static Regeneration (ISR) allows you to create or update content without redeploying your site. ISR has two main benefits for developers: better performance and faster build times.
To enable ISR in a Nuxt route, add a routeRules
option to your nuxt.config.ts
, as shown in the example below:
export default defineNuxtConfig({
routeRules: {
// all routes (by default) will be revalidated every 60 seconds, in the background
'/**': { isr: 60 },
// this page will be generated on demand and then cached permanently
'/static': { isr: true },
// this page is generated at build time and cached permanently
'/prerendered': { prerender: true },
// this page will be always fresh
'/dynamic': { isr: false },
},
});
You should use the isr
option rather than swr
to enable ISR in a route. The isr
option enables Nuxt to use Vercel's Edge Cache.
To summarize, using ISR with Nuxt on Vercel offers:
- Better performance with our global Edge Network
- Zero-downtime rollouts to previously statically generated pages
- Global content updates in 300ms
- Generated pages are both cached and persisted to durable storage
Learn more about ISR with Nuxt.
Image Optimization helps you achieve faster page loads by reducing the size of images and using modern image formats.
When deploying to Vercel, images are automatically optimized on demand, keeping your build times fast while improving your page load performance and Core Web Vitals.
To use Image Optimization with Nuxt on Vercel, install the @nuxt/image-edge
package:
pnpm i @nuxt/image-edge
Then, add the package name to the modules
key in your Nuxt config object:
export default defineNuxtConfig({
modules: ['@nuxt/image-edge'],
});
Finally, add the package to the modules
array in your Nuxt config:
export default defineNuxtConfig({
modules: ['@nuxt/image-edge'],
});
You can then embed an optimized image with the <nuxt-img>
component. The following example demonstrates a basic Vue component with a 100px by 100px image optimized with <nuxt-img>
:
<template>
<nuxt-img src="/nuxt-icon.png" width="100" height="100" />
</template>
To configure your @nuxt/image-edge
module with global options, add an image
property to your Nuxt config.
See the Nuxt Image configuration docs for a list of the options available.
The following example demonstrates a Nuxt config that uses the domains
option to enable image optimization on remote images from nuxt.com
:
export default defineNuxtConfig({
image: {
domains: ['nuxt.com'],
},
});
To summarize, using Image Optimization with Nuxt on Vercel:
- Requires zero-configuration for Image Optimization when using
nuxt/image
- Helps your team ensure great performance by default
- Keeps your builds fast by optimizing images on-demand
Learn more about Image Optimization
The Nuxt team does not recommend deploying legacy versions of Nuxt (such as Nuxt 2) on Vercel, except as static sites. If your project uses a legacy version of Nuxt, we recommend implementing Nuxt Bridge or upgrading with the Nuxt team's migration guide.
If you still want to use legacy Nuxt versions with Vercel, you should only do so by building a static site with nuxt generate
. We do not recommend deploying legacy Nuxt projects with server-side rendering.
See our Frameworks documentation page to learn about the benefits available to all frameworks when you deploy on Vercel.
Learn more about deploying Nuxt projects on Vercel with the following resources:
Was this helpful?