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.