Deploy a Full Stack Next.js App to Vercel

Deploying a Next.js app to Vercel is a quick process thanks to the work that Vercel has done to make it easy. Next.js is a React framework built by Vercel so it makes sense they would make their hosting experience as smooth as possible.

For the simplest way to deploy a Next.js app to Vercel, you can use a GitHub repo and deploy it by visiting deploy.new in your browser.

deploy.new

Otherwise, you can login to your Vercel Dashboard and click the New Project button.

Let's dig a little deeper and create a new Next.js app so we can deploy it to Vercel.

We can create a new Next.js app by using Create Next App and then we can deploy it to Vercel.

bash
npx create-next-app my-super-cool-next-app

Push this directory to your GitHub repo and then you can go into the Vercel Dashboard to deploy from GitHub.

The cool thing about deploying Next.js to Vercel via GitHub is that Vercel will automatically deploy your app whenever you push to your GitHub repo. It will also provide you with deploy previews for git branches so you can examine what your branch looks like without pushing it to the production branch.

Vercel Deploy Previews

Notice how we can see the different branches being deployed above.

We have the ability to add environment variables to our Next.js app. This is useful for setting things like the API endpoint for our app.

Vercel Environment Variables

Real user monitoring is a huge part of the development process. Vercel provides you with a real-time analytics that shows you how your app is performing and how it is being used.

Vercel Analytics

The great thing about these analytics is that these are from real users visiting your app. These aren't simulated benchmarks like Lighthouse provides. These are real user actionable insights that you can use to make your app better.

We can supply dynamic data to our pages at build-time using the getStaticProps() fetchin ghook. This is great for marketing pages where data doesn't need to change too often and speed is the priority.

By using getStaticProps, we can fetch all the data at build-time and then use it to render the page. This means we don't have to worry about fetching data on the client side.

For instance, we can add a getStaticProps function to our pages/index.js file.

js
import Head from "next/head";

// add some SEO to our page using next/head

export default function Home({
  title = "Hello World!",
  metaContent = "Generic SEO pitch",
  copy = "I'm having writer's block.",
}) {
  return (
    <>
      <Head>
        <title>{title}</title>
        <meta content={metaContent} />
      </Head>

      <div>
        <h1>{title}</h1>
        <p>{copy}</p>
      </div>
    </>
  );
}

export const getStaticProps = async () => {
  // This is a full server-side Node environment,
  // which means that you can make network requests,
  // talk to databases, read from the file-system,
  // and do whatever you want to fetch your data.

  return {
    props: {
      title: "My Amazing Startup",
      metaContent: "Amazing SEO poetry",
      copy:
        "I'm in the business of making people smile. That's all I'm here for.",
    },
  };
};

Everything is the same as a typical React application, but there are a few differences. We are setting page metadata using next/head. In a React application, you'd probably use something like react-helmet.

We're also exporting a getStaticProps function that will provide the props to the main component. This is a great place to fetch data from the server. In this case, we are just passing in static data.

Next.js blurs the line between static and dynamic. Just because we fetch data statically, doesn't mean that our pages have to use the same data until you re-deploy. Next.js can give us Incremental Static Regeneration so that we can update existing pages by re-rendering them in the background as traffic comes in.

To tell Next.js when to regenerate our pages, we can add in the revalidate property which tells Next.js when to re-render the page. By default, revalidate is set to false so it will only re-render the page when your app is re-deployed (aka the next time you push to GitHub).

js
export const getStaticProps = async () => {
  return {
    props: {
      // omitted for brevity
    },
    revalidate: 1, // number of seconds to wait before revalidating
  };
};

Sometimes you may have highly dynamic content that needs to change often, maybe even on every page load. This could be something like a users' dashboard where they can see their profile, update their profile, and see their recent activity.

For this scenario, Next.js provides getServerSideProps() which is a great place to fetch data from the server. It operates very similar to the getStaticProps function.

js
export default function Dashboard({ analytics }) {
  return (
    <div>show the users analytics here</div>
  )
}

// go get the analytics from the server on every page load
export const getServerSideProps = async ({ req }) => {
  const analytics = await fetchAnalytics(req);

  return {
    props: { analytics },
  };
};

We are destructuring a Node.js HTTP Incoming Message object from the req parameter. This is similar to what building out serverless functions would look like.

This page is completely rendered in the server and then sent back to the client. It should be mentioned that rendering a page this way will incur a slight performance hit. This is by design since the server has to process the request, make API calls, and then render the page.

API Routes allow us to create HTTP request handlers using the same file-system routing structure that we saw on the frontend. When we created our project with create-next-app, an API route was already generated for us at pages/api/hello.js. It had the following contents:

js
export default (req, res) => {
  res.statusCode = 200
  res.json({ name: 'John Doe' })
}

If you navigate to <localhost:3000/api/hello>, you'll get a JSON response from the function.

When you deploy your Next.js application to Vercel, you'll see get the API route deployed also.

Next.js is a comprehensive framework that gives us many ways to grab our data and to render our application. Personally, I think it's the most flexible and powerful framework I've ever used. I've used it for a number of different projects and I'm very happy with the results.

Using any combination of the above will allow us to build out fast, performant, and scalable applications.

Want to improve your coding and design skills?

I'm continually researching the best practices and tools for coding.
Join 50,000+ developers looking to make cool stuff.

We value your privacy. 1-click unsubscribe.

Chris Sev

Chris Sev

Chris Sev is the co-founder of Better Dev. Coding better every day. Previously he created Scotch.io which was acquired.

Comments

What did you think of the article? Let us know!
(these comments are powered by GitHub issues and use 0 trackers)