gatsby: Preventing 301 redirects on URLs with no trailing slashes (Netlify)
Summary
URLs with no trailing slash on sites hosted by Netlify lead to an immediate 301 redirect to the page with a trailing slash.
foo.com/bar
--> foo.com/bar/
This has a performance cost and implications for SEO.
Is there a Netlify configuration that resolves these URLs without redirecting?
Relevant information
While this question is specific to Netlify, I did a quick review of other Gatsby sites featured in the Showcase and saw the same behaviour in many, but not all cases, for example:
Hopper /company - 301 redirect (Netlify) Impossible Foods /mission - 301 redirect (unknown) Cajun Bow Fishing /bows - 301 redirect (Netllify) Braun /shavers-for-men - 200 no redirect (unknown)
Environment (if relevant)
Same behaviour in Gatsby v1 and v2. I’m using gatsby-plugin-remove-trailing-slashes and gatsby-plugin-netlify. Within the project all Links point to the non-trailing slash version.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 44
- Comments: 67 (22 by maintainers)
@wardpeet @KyleAMathews Would like to bring your attention to this issue again because it’s a major problem for SEO, as many people in the tread already mentioned. Asking for PRs is great, but this particular one looks to be related to some of the core functionalities of the Gatsby engine, so I myself wouldn’t take responsibility touching it, not knowing all ins and outs of Gatsby.
Could you or someone with deep knowledge take a look and offer some kind of solution?
Also, issue is not related to Netlify or Github pages. It can be reproduced locally, I have it on Firebase Hosting for production.
Additionally, there is already a PR from @cosmn. Maybe it already solves the issue or can be used as an idea on what can be done?
If you’re using Gatsby + Netlify, here’s how we solved it.
First, any pages in the
/pages
directory, which are created automatically by Gatsby, will have a trailing slash. You can see this behavior by entering a URL without a trailing slash directly into the search bar. The network tab will show a 301 as the page is redirected to the one with the trailing slash.Try running this GraphQL query and you will see that the path for these pages has a trailing slash.
To remove the trailing slash from the page path, you can add this code snippet from the Gatsby docs to your
gatsby-node.js
file:Next, you need to turn off the pretty URL setting in Netlify. If you have Asset optimization disabled, enable it, turn off pretty URLs, and then disable it again.
Push a new build and then observe the network requests for a page that had a trailing slash. For instance, after typing
https://www.software.com/code-time
then pressingEnter
, the first request is a 200 (there isn’t a 301 like before):If anyone has any better solutions, let me know! We haven’t solved the trailing slash on
localhost
.This is definitely still an issue, and we’ve experienced SEO penalties as well. Additionally, turning off Netlify’s pretty URLs feature seems to result in errors stating “Missing resources for /“ or “Missing resources for /slash/“. We’ve tried solutions recommended here: https://github.com/gatsbyjs/gatsby/issues/11524 but haven’t had any luck.
Just wanted to reply that we are looking forward to this bug being resolved. We are using urls without trailing slashes btw, we have the issue that Twitter/Facebook will not show the thumbnail we set, because the url is redirected to the version with a trailing slash. (Twitter Card Validator will return:
WARN: this card is redirected to https://foo.com/bar/
when submittinghttps://foo.com/bar
). Twitter will only pick up the thumbnail after manually using Twitter Card Validator to enter the url, and it will forget it after a week (Twitter re-indexes card content every week or so, and it won’t index the urls that are hidden behind a redirect).The performance cost is the synchronous delay for the first byte of useful data caused by the redirect.
Using the Hopper example above, visiting https://www.hopper.com/company takes 150-300ms for the redirect, before any page data is received. On cellular connections with high latency it can add up to 1s.
Hey 👋🏻
I know this issue lapsed and got closed but I really think it’s important to recap on a couple of things here. The impetus for this issue is that a) there’s a disconnect between Gatsby’s routing defaults and Netlify’s routing configurations, and b) there are serious SEO penalties in play if a Gatsby site doesn’t have the trailing-slash / no-trailing-slash issue solved, since a site serving the same content on both URLs (duplicate content) gets knocked on SEO pretty hard. Technically this isn’t Gatsby’s fault, but as it pertains to all Gatsby users hosting on Netlify, it does seem like a major issue… or a major risk at the very least.
Solving this problem by disabling “Pretty URLs” in the (yes, awfully borked / painful UX’d) Netlify Asset Optimization panel can open your site up to the duplicate content issue since content may be available at both the un-slashed and the slashed version of your URL path. It’s important too to note that if a Gatsby site is available on both
/test
and/test/
but ‘fixes itself’, you may just be seeing the Gatsby runtime adjust your address bar via the Browser History API - the super important part has nothing to do with what happens when Gatsby actually runs in the browser - it’s the part where Netlify is serving the same content on multiple URLs - the slash and the non-slash paths.This is fixable and there is a way to get everything working smoothly and on a unified path / slash structure, but it’s not disabling ‘Pretty URLs’. The tl;dr: is that Netlify really works best / has biases toward using the trailing slash, and unified content pathing on Netlify requires the trailing slash. I elaborated on this in another Gatsby GH thread here:
https://github.com/gatsbyjs/gatsby/discussions/27889#discussioncomment-254854
But I would definitely urge folks to carefully check (from a CLI HTTP tool preferably) which paths (slash and/or no-slash) are resolving to their content on their sites. If both the slash and no-slash paths are resolving to your content, your SEO will hurt for it.
Hope that helps 😕
This is indeed the case.
Here is how your netlify config should look like:
Disabling optimization at the top level apparently turns on the pretty URLs, even though it visually looks like that isn’t the case:
So don’t check the checkbox next to “Disable asset optimization”
this also happens with nginx server.
EDIT: this issue has nothing with gatsby. it is web server misconfiguration. I have checked output files and it seems gatsby creates a directory for each page and and index.html in it. So I had to change my nginx url resolving as following:
The
$uri/index.html
is resolving correct file without redirect. If that doesn’t exists or it is$uri/
( most nginx conf examples uses that ) it will create a redirect with trailing slash. It is also stated in nginx documantation.I have not used Netlify but I believe same thing would apply to it.
This is a problem in AWS as well. Gatsby is a scam. my solution is sadly, to append a forward slash everywhere. oneliner:
if (to[to.length - 1] != "/") to += "/"
ifto
is the link variable.This is true but I haven’t noticed any difference in behaviour with or without “Pretty URLs”;
/foo
redirects to/foo/
in either case. The desired behaviour is to rewrite slashless urls to resolve without redirecting.Making
/foo/
canonical is a workaround for the SEO penalties but AFAIK a full solution would only be possible in Netlify’s routing layer… or by abandoning Netlify in favour of custom url rewriting …or by adopting slash/ urls. It’s an unfortunate situation.This is a bug in the Netlify UI.
Here’s a fix: https://community.netlify.com/t/remove-trailing-slash-redirect-for-gatsby-gatsby-cloud-netlify-website/20976/8
Thanks for all the helpful comments which lead us in the right direction.
If it still doesn’t work after setting it to @mlenser’s comment (https://github.com/gatsbyjs/gatsby/issues/9207#issuecomment-695913229), make sure to check your
netlify.toml
for pretty_urls.Settings in the toml take precedence, see the docs: https://docs.netlify.com/configure-builds/file-based-configuration/#deploy-contexts
Guys, it’s a setting within Netlify as described above. Perhaps a new issue needs to be created.
On Tue, 23 Jun 2020, 16:29 Lawrence Whiteside, notifications@github.com wrote:
Not at the moment. The closest would be name your pages like
page.html.js
. My advice to you would be to stick with trailing slashes. For non-trailing slashes to work you’ll need to do some server-side url rewriting.@KyleAMathews
@KyleAMathews this is seo danger This subject isn’t explained at all in https://www.gatsbyjs.org/docs/gatsby-link/ If someones decides to use no-trailing-slash-urls, a couple of days later the google serp becomes full of 301 redirections for your site.
@0505gonzalez were you able to figure out a solution for this issue?
Just landed here as we’re having the same problems with the url parameters getting lost in the redirect from the version without the trailing slash to the version with the trailing slash.
Only difference is that we’re on S3 + Cloudfront.
We might look into using Lambda@Edge to handle the redirect unless we can figure out a way to get it to work with gatsby.
Update:
For our case, we implemented the fix from https://www.ximedes.com/2018-04-23/deploying-gatsby-on-s3-and-cloudfront/ with the following lambda js function:
I’m still trying to figure out what’s the best thing to do here, because I think as-is, there’s a negative impact to our SEO just because now we’re delivering the same page for the trailing and non-trailing slash version. Likely I will add a permanent redirect for the trailing slash version here too.
If you’re not using AWS/Cloudfront, I think you’d be able to accomplish this with Cloudflare Workers.
If you want your website to not have any trailing slash and also work with Netlify you can use the
gatsby-plugin-netlify
and ingatsby-node.js
addthis will redirect all trailing slash to non-slash paths with 301 status code. Note if you are also using
createPages
Gatsby node API you’ll need to add it there also@alvinometric I’m not sure — I’ve sent this over to our UI team for review. it does look like if this isn’t a bug, it could do with some clarification
I’ve just lost 3 hours because of this.
BOLEST.
This is not the case, even if you have a blank nginx config, any attempt to access a valid directory will result in a 301 with the trailing slash. It’s a common misconception that it is related to the
try_files
. The documentation is also poor surrounding this, the location documentation makes it seem like the 301 redirect is only for routes that are proxied.I made a plugin from a code that I normally use in websites hosted at Netlify. It creates a
.html
file for each page, which disables the 301 redirect for paths without trailing slashes. It works very well with simple websites, I hope it helps someone. More info can be found on the plugin page.Can someone summarise the current situation?
Solution: still WIP.
Hack:
Please feel free to correct me and I’ll amend/delete the above.
I don’t think that this issue is related to Netlify or Github pages. I can reproduce it locally running
gatsby serve
, which appears to be expected behaviour Gatsby’s redirect handling.@lloydh / @luukdv - can you reproduce locally?
@himynameistimli I did find a solution, proposed a code change in another thread. But seems like it might not be accepted so have not created a PR.
The gist of it:
/somepage
, it will redirect to/somepage/
because it’s a directory (actual file is/somepage/index.html
./somepage.html
instead of/somepage/index.html
@jaapstronks Are you by any chance running with netlify? Managed to fix this issue here https://github.com/gatsbyjs/gatsby/issues/15317#issuecomment-530048373
I’ve just started evaluating Gatsby. Is there a way that, say for a given path
/foo
, have Gatsby generatepublic/foo.html
instead ofpublic/foo/index.html
?Just to clarify, the ‘Pretty URLs’ option in netlify WILL redirect you to the trailing slash variant: