301 Redirects with Next.js

Last week, 3blades - the company I work for - launched our new website using Next.js/Now. In the process, we moved our company blog from our main website to a Medium site. Consequently, we had a block of 301 redirects from 3blades.io/blog to blog.3blades.io. I looked through the Next.js documentation and googled around, but I couldn't find any 301 redirect examples. Since Next.js let's you use any custom server you want, I figured I could hand-wire it using Express. There's an Express example site in the Next.js repo I used for reference.

First, I installed express and created a server.js file with the following code (essentially the one from the example with extraneous parts removed):

const express = require('express')
const next = require('next')
const { join } = require('path')

const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  const server = express()

  server.get('*', (req, res) => {
    return handle(req, res)
  })

  server.listen(3000, err => {
    if (err) throw err
    console.log('> Ready on http://localhost:3000')
  })
})

This got the site working in the exact same way as running next. I put the redirects in an array of objects, with each redirect having a from and to key:

const redirects = [
  { from: '/old-link-1', to: '/new-link-1' },
  { from: '/old-link-2', to: 'https://externalsite.com/new-link-2' },
]

Then, inside app.prepare(), I iterated over the redirects, adding a handler for each onto the express instance server.

redirects.forEach(({ from, to, type = 301, method = 'get' }) => {
  server[method](from, (req, res) => {
    res.redirect(type, to)
  })
})

redirect.from is used as the handler path and redirect.to is passed to res.redirect. Each redirect can optionally define the HTTP method (GET, POST, etc.) and response code (301, 302).

I've included the full server.js code below:

const express = require('express')
const next = require('next')
const { join } = require('path')

const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

const redirects = [
  { from: '/old-link-1', to: '/new-link-1' },
  { from: '/old-link-2', to: 'https://externalsite.com/new-link-2' },
]

app.prepare().then(() => {
  const server = express()

  redirects.forEach(({ from, to, type = 301, method = 'get' }) => {
    server[method](from, (req, res) => {
      res.redirect(type, to)
    })
  })

  server.get('*', (req, res) => {
    return handle(req, res)
  })

  server.listen(3000, err => {
    if (err) throw err
    console.log('> Ready on http://localhost:3000')
  })
})

Lastly, I edited dev and start scripts in package.json to the new configuration:

{
  "dev": "node server.js",
  "start": "NODE_ENV=production node server.js"
}

With that, the 301 redirects are all set up. This code is running in production for us beautifully. Hope the walkthrough was helpful!

NOTE: The 3blades website is entirely open-sourced, so you can check out the source code.

© 2017 Ray Gesualdo. All rights reserved.
Website generated with <Phenomic />