2
votes

My site has a few dynamic routes that result in thousands of hydrated pages. The pages follow a url structure like: /artists/[id]/[slug] or /concerts/[year]/[month]/[day]/[slug]. Currently, my page structure mimics those routes: /pages/artists/[id]/[slug].tsx and /pages/concerts/[year]/[month]/[day]/[slug].tsx.

The route with slug is preferred, but the site should gracefully redirect when the slug is not available. For example, I would like to have any request going to /artist/id be redirected to /artist/id/slug. And likewise, I'd like to do some redirecting for various parts of the concerts urls.

I originally tried specifying the redirects in next.config.js like:

module.exports = {
  ...
  async redirects() {
    const [allArtists, allConcerts] = await Promise.all([...]);
    return [
      ...allArtists.map((artist) => {
        return {
          source: `/artists/${artist.id}`,
          destination: `/artists/${artist.id}/${slugify(artist.name)}`,
          permanent: false,
        };
      }),
      ...allConcerts.map((concert) => {
        return {
          source: `/concerts/${concert.year}`,
          destination: `/tours/${concert.year}`,
          permanent: false,
        };
      }),
      ...allConcerts.map((concert) => {
        return {
          source: `/concerts/${concert.year}/${concert.month}`,
          destination: `/tours/${concert.year}`,
          permanent: false,
        };
      }),
      ...allConcerts.map((concert) => {
        return {
          source: `/concerts/${concert.year}/${concert.month}/${concert.day}`,
          destination: `/concerts/${concert.year}/${concert.month}/${concert.day}/${slugify(concert.name)}`,
          permanent: false,
        };
      }),
    ],
  },
};

However, as of today, vercel/next.js does not support more than 1,000 redirects specified in that file.

I tried to return redirect: pathWithSlug from getStaticProps, but get the following error:

Error: `redirect` can not be returned from getStaticProps during prerendering

Any ideas or approaches for how I can accomplish this behavior?

2

2 Answers

1
votes

vercel/next.js does not support more than 1,000 redirects specified in that file.

You weren't kidding, this is something important to consider before moving into the platform. Some ideas & compromise:

  • Use getServerSideProps for pages/artists/[id] and use redirect there

  • Use the same content for pages/artists/[id] as pages/artists/[id]/[slug], but set canonical url to avoid SEO penalty

0
votes

First, you could significantly reduce the number of entries for the /concerts/* to /tours/* redirects by using path matching.

async redirects() {
    return [
        // ...
        {
            source: '/concerts/:year/:month',
            destination: '/tours/:year',
            permanent: false
        },
        {
            source: '/concerts/:year',
            destination: '/tours/:year',
            permanent: false
        },
        // ...
    ]
}

Unfortunately, the same cannot be done for the other paths. This alone could potentially reduce the number of entries below 1000 - depending on the amount of artists/concerts you have - but sooner or later it would become a problem again.

Second, to address the remaining paths, I would convert your /artists/[id]/[slug] and /concerts/[year]/[month]/[day]/[slug] routes into dynamic catch-all routes:

  • /artists/[...slug]
  • /concerts/[...slug]

This would allow the /concerts/[...slug].tsx page to match both /concerts/2020/08/20 and /concerts/2020/08/20/concert-name URLs, meaning you wouldn't need a redirect for these pages at all. The same would apply for the artists/* routes.

As @DerekNguyen mentioned in his answer, having a canonical URL that would be used in both for SEO purposes would be ideal.