withastro / roadmap

Ideas, suggestions, and formal RFC proposals for the Astro project.
320 stars 30 forks source link

Redirects #466

Closed natemoo-re closed 1 year ago

natemoo-re commented 1 year ago

Body

Summary

It would be useful if Astro could support redirects for static builds. Possibly for server builds, too?

Sometimes users want to rename a route or refactor how pages are organized. It's not possible to just rename a page as there may be links pointing to it, so redirects have to be generated. While this is possible to do manually, it's not very convenient.

Background & Motivation

Redirects for static and server mode are fairly straight-forward to implement. Other tools like Jekyll expose this ability, and hosting providers do as well.

It would be helpful if Astro could generate these automatically as a convenience. This feature could also normalize the implementation across hosting providers and output mode.

Goals

Non-Goals

None at this time.

Example

API TBD, but this could either be a built-in redirect configuration

import { defineConfig } from 'astro/config';

export default defineConfig({
  redirects: {
    '/foo/bar': '/unicorn/rainbow'
  }
})

or exposed as an official integration

import { defineConfig } from 'astro/config';
import redirects from '@astrojs/redirects';

export default defineConfig({
  integrations: [
    redirects({
      '/foo/bar': '/unicorn/rainbow'
    })
  ]
})
pilcrowonpaper commented 1 year ago

It would be great if I can define a redirect response inside getStaticPaths, and for a redirect response inside frontmatter to just work like in SSR mode.

tony-sull commented 1 year ago

This could be a really interesting to host adapters! The @astrojs/netlify integration could automatically build the _redirects file

matthewp commented 1 year ago

@tony-sull That's my thinking too. There was some debate on whether this should be an integration or not, but having it as an integration means that things like the netlify adapter can't easily use it. So it feels better to be in core.

lilith commented 1 year ago

I have a lot of websites that specify multiple redirects (Aliases:) in the frontmatter of each markdown page. Specifically, a web page/file can specify which source paths should redirect to itself.

Given that some of my websites have been up for 15+ years and gone through various CMSes (most recently Hardwired in 2012), there are a few hundred redirects. I wrote Hardwired out of my desire for file-based routing, speed, and simplicity, but... Astro has now adopted most of the features I needed and I'd love to tell everyone to abandon Hardwired and move to Astro.

Being able to collect and sort these frontmatter redirect-from paths into a _redirects file (or the equivalent Vercel or Cloudflare alternative) during SSG would be amazing and a huge help for me to be able to adopt Astro for all of my websites. Without redirects, migration is quite difficult. And I'm religiously opposed to broken links :)

I'd love to see host/adapter-specific configuration generation as an option - HTML redirect placeholders are a nice fallback, but hardly ideal.

matthewp commented 1 year ago

Use-case from @delucis:

i18n 404s in static sites — this usually needs a redirect set-up to match /[lang]/404 (we do this in netlify.toml in docs).

matthewp commented 1 year ago

Current implementation is:

import { defineConfig } from 'astro/config';

export default defineConfig({
  redirects: {
    '/foo/bar': '/unicorn/rainbow'
  }
})

Also you can use Astro.redirect in an Astro component:

---
return Astro.redirect('/');
---

Previously the latter was disallowed in SSG mode but will be allowed in the new version (is the plan).

lilith commented 1 year ago

Is this client side or does it compile to a redirects file?

On Thu, May 11, 2023, 1:57 PM Matthew Phillips @.***> wrote:

Current implementation is:

import { defineConfig } from 'astro/config'; export default defineConfig({ redirects: { '/foo/bar': '/unicorn/rainbow' }})

Also you can use Astro.redirect in an Astro component:

---return Astro.redirect('/');---

Previously the latter was disallowed in SSG mode but will be allowed in the new version (is the plan).

— Reply to this email directly, view it on GitHub https://github.com/withastro/roadmap/issues/466#issuecomment-1544594671, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA2LHYGCTMLDCGFMJAKULDXFVAEPANCNFSM6AAAAAAUQM5N3Y . You are receiving this because you commented.Message ID: @.***>

matthewp commented 1 year ago

@lilith When using an adapter (that supports some type of redirects file) it will compile to that. Otherwise it will create .html files with the meta refresh tags.

lilith commented 1 year ago

This includes Astro.redirect? Is there a frontmatter equivalent for .md and .mdx?

On Thu, May 11, 2023, 2:21 PM Matthew Phillips @.***> wrote:

@lilith https://github.com/lilith When using an adapter (that supports some type of redirects file) it will compile to that. Otherwise it will create .html files with the meta refresh tags.

— Reply to this email directly, view it on GitHub https://github.com/withastro/roadmap/issues/466#issuecomment-1544622695, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA2LH4LETAZATX7VCH7JBLXFVC4VANCNFSM6AAAAAAUQM5N3Y . You are receiving this because you were mentioned.Message ID: @.***>

matthewp commented 1 year ago

No, you would do it in the top-level redirects config. Is there a use-case for doing it in Markdown?

lilith commented 1 year ago

Is there a way for me to add this functionality via plugin or would I need to fork? I have hundreds of .md files with redirects in front matter (inbound, mostly).

On Thu, May 11, 2023, 2:32 PM Matthew Phillips @.***> wrote:

No, you would do it in the top-level redirects config.

— Reply to this email directly, view it on GitHub https://github.com/withastro/roadmap/issues/466#issuecomment-1544639090, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA2LH2323MMRP5N7FGYPLDXFVEGBANCNFSM6AAAAAAUQM5N3Y . You are receiving this because you were mentioned.Message ID: @.***>

jlarmstrongiv commented 1 year ago

Since middleware works with both SSG and SSR, I would expect using redirect to create an html redirect with page content like:

<head>
  <meta http-equiv="Refresh" content="0; URL=https://example.com/" />
</head>

These placeholders are important as a backup, such as when I can’t control the server. It may be possible with middleware by returning an html response with the html redirect, rather than using the built-in redirect function.

matthewp commented 1 year ago

@lilith we could possibly support that. Are you using another tool that supports this?

lilith commented 1 year ago

Yes, https://github.com/imazen/hardwired supports the following front-matter

-

Aliases: - Space delimited list of domain-local URLs to redirect to the current page. Use '+' to represent spaces in URLs

Redirect To: - Turns a page into a placeholder for a remote URL rediret

By far, incoming 'aliases' redirects are more useful, since you always need a destination page file for the content, but lots of cluttered empty files are a pain.

When your site is 15 years old, you collect a lot of redirects 😅

On Fri, May 19, 2023, 1:14 PM Matthew Phillips @.***> wrote:

@lilith https://github.com/lilith we could possibly support that. Are you using another tool that supports this?

— Reply to this email directly, view it on GitHub https://github.com/withastro/roadmap/issues/466#issuecomment-1555120275, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA2LHY4FO2NTOZEMONMZSTXG7BBRANCNFSM6AAAAAAUQM5N3Y . You are receiving this because you were mentioned.Message ID: @.***>

tordans commented 1 year ago

Thanks for adding this! Please let me know if there is a better place for those comments. I am using the new redirect feature and have those questions / comments:

Add noindex-tag to redirect pages

I suggest to add a <meta name="robots" content="noindex"> (the follow is implicit) to the rendered templates by default. Just to make absolutely sure that all bots recognize the URL as such. That should also help with social sharing bots that do not follow the redirect.

Add a text links for bots to follow

In the same spirit, I think it would be saver to also add a text link in the body of the page for bots to follow. <body><a href="{TO}>Redirecting from <code>{FROM}</code> to <code>{TO}</code>...</a> (or similar). (Disclaimer: I did not see any docs from google recommending this but it should make the system safer.)

Add a canonical tag to the page

In the same spirit, adding <link rel="canonical" href={TO} /> is a signal for bots to re-allocate the seo signals to the new URL. (Disclaimer: I did not see any docs from google recommending this but It is how I interpret the SEO chain.)

Allow temporary redirects

It looks like, at least google understands the meta tag redirect with a timer value > 0 as temporary redirects: https://developers.google.com/search/docs/crawling-indexing/301-redirects#metarefresh

To create a delayed redirect, which is interpreted as a temporary redirect by Google, set the content attribute to the number of seconds that the redirect should be delayed.

matthewp commented 1 year ago

@tordans Ah perfect, this is all great advice! I'll make sure this is added to our HTML based implementation.

matthewp commented 1 year ago

Closing as this is completed and in stable.

lilith commented 1 year ago

What would be a good place to add front-matter support for inbound redirects?

matthewp commented 1 year ago

You can add a new Discussion about this.

The tricky thing here is that we would need to read all of the files to know if something is a redirect. The way our dev server works is that we only read a file the first time there is a route match. So to do what you are suggesting, we'd need some method to get that information out.