Deploying with Custom Serverless Next.js Routing

Migrate from a Next.js app with a custom server to a serverless Next.js app using Now routes.

Next.js offers developers a built-in routing system that allows you to link to other pages whilst also giving those pages a custom URL. When a user refreshes the custom URL, however, the browser will not be able to load the link because the page was previously routed client-side. To resolve this, we need to also handle routing server-side.

Warning: This guide requires Next.js 9+ to work correctly.

Preface: Next.js Routing

When you link to a page within the same Next.js app, you can provide two options. The first and required option is href. This is a link to the page as it exists in the pages directory. The second is as which describes the URL Next.js should show when routing to that page.

For example, if you have a page located at pages/product.js in your codebase, you can use the href option with the value /product?name=<product_name> to route and render that page with a query parameter, however, if you want to show the URL /product/<product_name>, you can use the as option to format the URL when routing.

This is an amazing feature of Next.js, however, it cannot control how the server routes to the app if the routes are not defined with the server.

The Old Custom Server Method

The solution to this problem was previously using a custom server. For example, you could create an Express app, catch the request to /product/<product_name> and route it to the /product?name=<product_name> file behind the scenes so that you can keep the custom URL:

server.get('/products/:name', (req, res) => {
  return app.render(req, res, '/product', { name: req.params.name })
})

An example custom server route capture and render method.

Warning: The custom server method will not work with the ZEIT Now 2.0 platform.

The New Routes Method

With Now and the serverless approach, each Next.js page is a separate entry point, making the sole custom server entry point a thing of the past for the good of performance and stability. Fortunately, Now 2.0 offers a solution, handling the configuration of routes for you.

By making use of Next.js path segments with Now, dynamic routing is achieved through the file structure. No longer are custom servers or additional configuration required, simplifying the process of building your app significantly.

By Example

If you are yet to set up routing for your Next.js app, this brief example describes how to use Next.js routing with Now to support custom URLs.

Step 1: Defining Pages

The first part of creating defined routes is to make sure those routes can be rendered as pages. In this example, we will have two pages, "index" (our homepage) and "product".

The index.js inside of our pages directory is just a small page that exports a heading and a paragraph of text with a link to our future products page using a Next.js Link component:

import Link from 'next/link'

export default () => (
  <div>
    <h1>Welcome to our Next.js website!</h1>
    <p>
      View our{' '}
      <Link href="/product/espresso">
        <a>espresso product</a>
      </Link>
      !
    </p>
  </div>
)

An example index.js file for our project.

Note: In a real app, the product name query parameter would most likely be dynamic based on other factors, but for simplicity, we'll use "espresso" as the product name.

Next, for our link to work, we need to create a /product directory inside of /pages, then a [name].js file inside of /product. This page displays the query parameter, which we receive with the Next.js getInitialProps lifecycle method, as the title and a simple paragraph:

const Product = ({ name }) => (
  <div>
    <h1>{name}</h1>
    <p>Welcome to our product page for {name}!</p>
  </div>
)

Product.getInitialProps = async ({ query }) => {
  return { name: query.name }
}

export default Product

An example [name].js file for our project.

Now, clicking the espresso product link will result in the URL path being /product/espresso while rendering the product page with the name query parameter set to espresso.

Step 2: Deploying

With the Next.js app setup complete, we can deploy our app using ZEIT Now with a single command.

now

Deploying our app with the now command.

If you are using either Now for GitHub, Now for GitLab, or Now for Bitbucket; pushing your code to your repository is all you need to do for Now to automatically deploy your app.

Once you deploy, you will receive a deployment URL which contains this example with a few styling tweaks for ease on the eyes: https://nextjs-routes.zeit.sh/



Written By
Written by timothytimothy
Written by timneutkenstimneutkens
on January 23rd 2019