Static site builders are pretty great, but how do you go about setting up redirects when you inevitably move or replace a page?
Thankfully, Netlify expects that you will eventually need to setup 301 and 302 redirects, and even allows you to redirect with a 404 or 200 response code too. Neat!
Their docs cover the format of the file pretty clearly, so I won't spend too much time rehashing that here, but suffice it to say, you need to have a file named _redirects
in the docroot, with one redirect per line. Obviously you could manually create that file and have it get passthru copied during the build of your static site, but who wants to manually maintain such a file when we can let the sitebuilder handle it for us?
I use 11ty, not on this site, but for my voice over site (oh yeah, did you know I'm also a voice over actor?) - which is what we'll be discussing here. I imagine the process would be pretty similar for other sitebuilders but this is what I know so this is what we're covering... 😎
I use nunjucks, liquid is basically the same syntax, so either way, create a file in your src
directory called _redirects.njk
(or .liquid as applicable).
Within that file we need a little bit of front matter:
---
permalink: /_redirects
eleventyExcludeFromCollections: true
---
This tells 11ty to keep it out of the collections.all
page collection, and to ensure it gets written to the file _redirects
in the docroot when the site is built.
Pretty easy so far, but that won't do anything other that create a blank file.
Ideally, we want to be able to just specify the old path in the front matter where the thing lives now or of the new page that replaced that old thing.
Say something like: redirectFrom: /some/old/url
Or maybe we even want to be able to optionally redirect a bunch of old pages to this one new page, like we combined a bunch of things into one consolidated page - probably not the best move for SEO, but hey, you do you.
In that case we might just want to do something like this:
redirectFrom: ['/some/old/url', '/some/other/old/url', '/yet/another/url']
Alrighty then - lets get to it!
Lets think through the steps logically, we need to iterate through every page in our site, and check if it has a redirectFrom
directive in its front matter, then determine if that's one url or an array of urls, and write out one redirect per line. For kicks, we'll also optionally support a redirectCode
property.
First, lets open up the 11ty config file and add a new filter
to determine if something is a string or not, this is how we'll check if our redirectFrom property is a string or an array - technically we probably ought to also check if it's an array, but we'll just assume it is if not a string since, we are the ones writing these files, after all...
Right. An is_string
filter, looks a little something like this:
// file: .eleventy.js
module.exports = (config) => {
// ..snip..
config.addFilter('is_string', function(obj) {
return typeof obj == 'string'
})
// ..snip..
}
Usage is simple, {% if thing | is_string %}
and so forth.
Alright, that's all the bits in place, now we can populate the rest of our _redirects.njk
file:
---
permalink: /_redirects
eleventyExcludeFromCollections: true
---
{%- for page in collections.all -%}
{%- if page.url and page.data.redirectFrom -%}
{%- if page.data.redirectFrom | is_string -%}
{{ page.data.redirectFrom }} {{ page.url }} {{ page.data.redirectCode or '301'}}
{%- else -%}
{%- for oldUrl in page.data.redirectFrom -%}
{{ oldUrl }} {{ page.url }} {{ page.data.redirectCode or '301'}}
{%- if not loop.last -%}
{{ '\n' }}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{{ '\n' }}
{%- endif -%}
{%- endfor -%}
So this will look at every page, and assuming that page has a url AND a redirectFrom, it'll check if the redirectFrom is a string and if so spit out the old url, new url and optional redirect code (defaulting to 301). If it's an array it'll do the same for each item in the array. Ensuring newlines are added after every individual line, without extra newlines (though that wouldn't hurt anything)
This will get rudimentary redirects working for your 11ty site hosted with Netlify straight away. What it does not cover is more complex redirects with query strings, params, and so forth.
Refer to the Netlify docs for details on the proper syntax for that. Config of that is beyond the scope of this blog post. While you're over there looking at the docs, take note you can also do fun proxy things by setting up redirects with 200 codes. Neat.