在单页面应用中,如何处理错误的URL(404错误)是正确的方式?

62

我目前正在使用angularjs编写一个Web应用程序,但我认为这个问题适用于任何在客户端进行路由的javascript框架(就像angular一样)。

在单页面应用程序中,如何处理错误的URL是正确的方式?

看了几个主要网站,我发现gmail会重定向到收件箱,如果您在https://mail.google.com/mail/下输入任何随机URL。这是在服务器端完成的(使用http 300代码)或在客户端完成的,具体取决于错误路径是在#字符之前还是之后。另一方面,Twitter对任何无效的URL显示真正的HTTP 404。第三个选项是显示“软”404,即纯客户端错误页面。

这些解决方案似乎适用于不同的情况。Twitter希望Twitter用户和推文链接成为真正的链接,以便人们可以共享它们,在新闻文章中发布它们等等,因此识别无效链接非常重要(如果我在我的网站上有一个损坏的推文链接,简单的爬行将告诉我)。另一方面,在Gmail中,您不需要在收件箱中分享链接,我甚至不确定链接是否真正是永久/持久的:似乎URL更新主要用于浏览器历史记录导航单页应用程序内。给出软错误的第三种方法可能适用于类似Gmail的情况,但没有合理的“默认”页面。
经过这么长的介绍,以下是一些具体问题:
  • 在单页应用程序中,如果URL无效,是否可以给出“软”错误页面而不是404错误,或者始终重定向到真正的404?
  • Gmail的代码可能完全没有漏洞,但如果出现错误导致无效链接最终重定向回收件箱,这可能比错误页面更令用户困惑。对于大多数没有像Gmail一样经过充分测试的Web应用程序,显示错误页面是否更好?
  • 要为单页应用程序实现真正的404,似乎需要在服务器端复制路由逻辑。有没有其他方法可以解决这个问题?
  • 重定向到404时,我认为用户应该能够看到导致错误的URL,可能在URL栏中。使用html5历史记录API,我认为可以通过简单地触发当前页面(带有错误的URL)的重新加载来实现,再结合上述服务器端路由。对于不支持此功能或使用哈希符号表示法的浏览器,似乎不可能。如何支持所有浏览器?

1
你的网站没有使用JavaScript能正常工作吗?你是通过JavaScript中的history.pushState还是URL中的segments来更新URL的? - Markus Unterwaditzer
1
@MarkusUnterwaditzer:关于重定向与显示软404:这是问题的一部分。在某些情况下,客户端显示404是可以接受的。但我喜欢HTTP 404具有已知的语义,自动化工具可以理解(用于测试、检查链接等)。 - jssebastian
1
这个问题没有明确的答案。Armin Ronacher写了一篇关于Battlelog所使用的方法的文章:首先在服务器端呈现网站,然后使用Javascript来呈现每次点击:http://lucumr.pocoo.org/2011/11/15/modern-web-applications-are-here/ - Markus Unterwaditzer
在未经过身份验证的情况下,应用程序中的内容将不可见,因此在这种特定情况下我不关心索引(类似于 Gmail 示例,但多个用户共享一个“收件箱”)。 - jssebastian
1
那么在你的情况下,只需显示一个类似404的消息即可。 - Markus Unterwaditzer
显示剩余3条评论
2个回答

9
如果您在意SEO,angular.io(至少在Google上)解决此问题的一种方式是使用noindex meta tag“指示软404状态,从而防止爬虫爬取页面内容”。显然,可以通过JavaScript将其添加到文档中。
或者,使用JavaScript,您可以重定向到一个页面,该页面将响应实际的HTTP 404状态代码。Google可以很好地理解JavaScript重定向。当您原来的/does-not-exist页面重定向到/404-error?from=does-not-exist时,它将与服务器返回的404状态代码相关联。 URL结构无关紧要,只有状态代码和重定向在这里非常重要。
你的其他选择是SSR(如Nuxt.js、Next.js、Angular Universal等)或预渲染(如prerender.io、puppeteer等),谷歌称之为动态渲染,即在搜索机器人请求时响应预渲染版本,而人类用户则使用正常的客户端渲染应用程序。

......在这种情况下,您可以使用预渲染版本响应搜索机器人请求,而人类用户则可以获得您的正常客户端呈现的应用程序。从SEO角度来看,如果用户请求例如'my-app.com/not-existent-path/blah/blah/blah',并且我的服务器响应具有404 HTTP状态代码的页面,但是在404页面呈现后,用户按下“转到主页”按钮,当按下该按钮时仅更改页面的某些内容并使用JS历史记录API而不向服务器发出新请求,那么这样做是否可以?即,页面呈现为404,应用程序通过历史API更改URL后。 - tonix
1
听起来还不错。如果你使用JS History API更改URL,无论你是从服务器、缓存还是其他方式获取新内容,对SEO都没有影响——因为搜索机器人不会点击你的“转到主页”链接,而是会向该链接中的URL发出新请求。JS History API只适用于您的人类用户。 - Denis Pshenov
3
如果有人看到这篇文章,这里有一个关于如何处理软404的有趣讲座链接:https://www.youtube.com/watch?v=vjj8B4sq0UI&t=30m15s(31:40 分钟处)。这是为 JavaScript fwdays 大会制作的演示文稿,其中有一个有趣的解释,说明为什么 noindex 元标记可能会引起不必要的副作用。 - Rose
1
@Rose,谢谢你的视频。公平地说,只有在响应本身中添加noindex元标记时,才会出现这个问题。但是,如果您通过JavaScript添加它,则不应该有问题。为了安全起见,我不会将noindex元标记作为默认选项添加(就像angular.io一样),而是只在需要时添加。 - Denis Pshenov

5

tl;dr: 如果你关心SEO,那么请放弃对哈希Bang的支持并选择PJAX

你是在制作应用程序还是网站?如果是网站,你需要返回404以避免混淆谷歌。它需要是真正的404,而不仅仅是显示页面未找到的消息(即200和消息“页面未找到”非常糟糕)。另外,你关心哪些浏览器的支持?

我认为应该避免整个哈希Bang服务器端渲染(即令人讨厌的Google SEO #! hack)。对于不支持pushstate的浏览器,要么使用真正的pushstate,要么重新渲染整个页面(而不是哈希更改)。

现在这很重要的原因是#!永远不应返回404,因为这没有意义,并且在不运行Javascript的情况下无法模拟服务器端。因此,如果您真的关心SEO,我会像PJAX一样做一些事情,并仅对路由使用真正的pushstate,然后只失败于旧的web 1.0。因此,我建议您分享的链接可以真正成为404,不应该有#!(传统的#是可以的,只要页面内容不会发生很大变化)。

最后,404大多数情况下并不是问题,而是30X即重定向响应。这是因为浏览器将自动处理重定向,因此您的Javascript AJAX调用永远不会看到30X(它们将获得重定向响应,即200)。要处理30X响应,您必须为每个请求发送一个标头,以指示重定向URL是/是什么(即您被重定向到了什么地方),以便不会破坏Pushstate历史记录。

当然,如果您需要支持像Twitter一样的哈希Bang(他们甚至杀死了哈希Bang),则可以利用Google Sitemaps和rel=nofollow来尝试减轻糟糕的SEO。


PJAX 对于从头开始构建的人来说很有趣。但是 AngularJS 框架支持 pushState,所以我想 PJAX 不是必需的。或者 PJAX 还有其他功能吗? - jssebastian
我现在正在开发一个应用程序,它不会被搜索引擎索引。但我对更普遍的了解这个问题很感兴趣。 - jssebastian
我之前不知道pushState和30x响应的问题,现在知道了。有没有相关文档、示例或教程可以提供参考? - jssebastian
具体来说,pjax-container 在概念上似乎与 angularjs 的 ng-view 相同。 - jssebastian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接