【问题标题】:AngularJS SEO for 404 Status for Document Similar to This WebsiteAngularJS SEO 用于类似于本网站的文档的 404 状态
【发布时间】:2017-01-09 11:38:10
【问题描述】:

我正试图弄清楚如何在我的 AngularJS 应用程序上为未找到的页面获取 404 文档状态错误,以保持良好的 SEO。我想做类似于 Red Bull Sound Select 网站的做法,但我不确定他们是如何做到的?

示例 404 网址

https://www.redbullsoundselect.com/no-page-here

正如您在上面的示例中看到的,URL 更改为 /404,并且您会收到 URL 中原始路径的 404 文档状态错误,即 no-page-here



在我的 AngularJS 应用中,我只有:

.otherwise({
    class: 'page-not-found',
    title: '404 Page Not Found',
    description: '404 Page Not Found',
    templateUrl: '/app/static/404.html',
    controller: 'mainController as mainCtrl'
});

我可以使用类似的东西:

otherwise({
    redirectTo: '/404'
});

这与 redbull 网站的类似,但它仍然没有给出 404 文档状态错误。 (还将 URL 更改为 404 而不是保留原始 URL,这对 SEO 也不是很好,但至少错误的 URL 不会被 Google 索引。)

我想我可以尝试在 Angular 中发出一个不存在的 http 请求以获得 404 xhr 状态,但我认为这还不够。

我读过一些建议使用 prerender.io 的 answers,但这是您必须支付的费用,这似乎有点多只是为了让 404 页面正常工作。

也许,我们可以在 .htaccess 中做些什么来以不同的方式处理 404 页面?目前我们已经重写规则,以便任何不存在的请求资源都将使用/index.html。也许我们可以对 Apache 处理 404 页面的方式例外。

更新

我在 redbullsoundselect.com 上发现他们在 app.js 中使用以下内容

$stateProvider.state("404", {
  url: "/404",
  templateUrl: "/views/site/404.html",
  controller: "NotFoundController"
});

虽然,我仍然不明白这个逻辑是如何运作的。我查看了他们的NotFoundController,但其中似乎没有发生太多事情。

像我这样使用ui.router 而不是ngRoute 可能与他们有关吗?

第二次更新

这是我的.htaccess 设置:

RewriteEngine On
  # If an existing asset or directory is requested go to it as it is
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
  RewriteRule ^ - [L]

# 如果请求的资源不存在,使用 index.html 重写规则 ^ /index.html

【问题讨论】:

  • 虽然 AngularJS 及其包含的路由由客户端处理,但您不能使用 AngularJS 返回404 not found。那是你已经建议的。当然,您可以创建一个 .htaccess 文件并为所有未配置的 AngularJS 路由返回 404。在您的客户端应用程序中配置 AngularJS 的路由时,您需要手动或使用自定义脚本管理 .htaccess 中的 URL。
  • @lin 谢谢,redbullsoundselect.com 做得怎么样?
  • 我不认为幕后有什么特殊的逻辑。我猜他们的服务器知道所有路由,并返回具有相同路径的相同索引文件,但它唯一做的是将状态代码更改为 404。应用程序像往常一样运行到 404 状态(否则)。而且我敢肯定他们讨厌这种逻辑,因为它使他们在应用程序中添加/更改状态时随时更改 url,但是谷歌强迫你这样做,这样你就不会在谷歌结果中出现重定向到的垃圾 url 404
  • @Dvir,但是他们如何更改 SPA 上的状态代码
  • @Holy 他们是从服务器上做的。例如,如果您使用带有 angularjs SPA 的服务器,则必须将任何请求重定向到 index.html 文件,并保持查询字符串不变。服务器获取带有 url 的请求,他知道该 url 不存在,所以他将响应状态代码更改为 404 并使用查询字符串重定向到 index.html(原始请求:domain/some-invalid-page) .然后 angular 自己玩,他找不到状态,所以它会重定向到 404 状态。这里唯一改变的是状态码。

标签: angularjs seo


【解决方案1】:

RedBull Sound Select 正在做什么

有效网址:https://www.redbullsoundselect.com/artists/gherbo

网址无效:https://www.redbullsoundselect.com/artists/gherbo2

打开 DevTools,在 Network 选项卡中选择“Preserve log”,打开无效 URL。

  1. Angular 应用加载了 200 或 304(如果在缓存中)
  2. 对/api/v1/groups/gherbo2?type=artist进行API调用
  3. API 以 404 响应
  4. Angular 代码执行 window.location.assign("/404"); artists-profile.js:577

他们提供 Angular 文件的 Express 应用程序知道有效的 URL 模式,如果 URL 与定义的模式不匹配,则发送 404。但是,如果 URL 匹配上述无效 URL 的模式,则 Angular 使用 window.location.assign 导航到新页面。

抓取工具 (GoogleBot) 的行为方式

  1. 假设 Google 访问了无效的网址
  2. 它得到的第一个响应码是 200
  3. 现在 Google 可能会也可能不会执行 JS。 Source
  4. 如果它执行 JS,Angular 会尝试将其导航到新页面。 (这里不确定爬虫会如何反应)

总的来说,在我看来,这对 SEO 来说不是很好的设置(但对用户来说,这很好)。我们正在为 SEO 的 Angular 部署中集成自托管 Prerender。

Prerender 是在 MIT 许可下开源的。

我们将其作为服务托管在 prerender.io,但我们也将其开源,因为我们相信基本的 SEO 是一种权利,而不是特权!

【讨论】:

  • 谢谢这是一个非常好的答案。所以他们已经为他们的快递服务器配置了发送到soundSelect angular 应用程序的路由?但是,当您到达未定义的路线时,您将被发送到 404 页面,这是 ng-app="soundSelect" 的一部分,如 html 标记所示。这是正确的吗,404 页面是他们的 Angular JS 应用程序的一部分,但是给出了 404 文档状态响应,我仍然没有完全理解。
  • 而/artists/gherbo2 URL 的行为与/no-page-here 不同。 no-page-here 不是 angularJS 应用程序的配置路由器,而 gherbo2 被重定向到带有 window.location.assign("/404") 的 404 页面(我认为 window.location.replace("/404") 会更好)。
  • 有趣的是,这个 redbull 网站似乎没有太多 indexed by google,所以我明白你对 Prerender 的看法,它似乎是唯一可靠的解决方案,并且如果自托管是免费的?
  • 他们的快速服务器配置为在请求已知 URL 模式时返回 Angular index html 状态为 200。当 /404 被命中时,相同的 html 文件将使用 404 代码提供服务
  • 响应头有x-powered-by:Express
【解决方案2】:

每当您获得 404 xhr 状态时,您都可以在 AngularJS 应用程序上实现 Page Not Found 的 404 文档状态错误。

angular.module('app', ['ui.router'])
       .config(config)
       .run(run);

config.$inject = ['$httpProvider', '$stateProvider', '$urlRouterProvider'];

function config($httpProvider, $stateProvider, $urlRouterProvider) {

    $httpProvider.interceptors.push('404');

    // For any unmatched url, redirect to /state1
    $urlRouterProvider.otherwise("/login");

    // Now set up the states
    $stateProvider

    // This will be helpfull if in your application you want to redirect it to state '404' based on some false condition occured.
    .state('404', {
       url: '/404',
       templateUrl: '/views/site/404.html'
    })
}

//This peace of code will be called when you will get http response 404 OR 403 xhr status.
angular.module('app').factory('404', unautherizedService);

unautherizedService.$inject = ['$rootScope', '$q', '$state'];

function unautherizedService($rootScope, $q, $state) {
    return {
        responseError: function(response) {
            if (response.status === 404 || response.status === 403) {
                $state.go('404'); // OR you can fire a broadcast event to logout from app and redirect to 404 page.
                event.preventDefault();
                return $q.reject(response);
            }
            return $q.reject(response);
        }
    };
};

【讨论】:

  • 感谢这看起来很有趣。我会检查一下。目前我正在使用 ngRoute。这只能通过 ui.router 实现吗?
  • ngRoute 也不能使用这种方法。我更喜欢 ui.router 而不是 ngRoute,因为 ui.router 提供了更多的灵活性和优势。
  • 这里是选择 ui-router 而不是 ngRoute 的一些常见原因: - ui-router 允许嵌套视图和多个命名视图。 - ui-router 允许您基于状态名称在状态之间建立强类型链接。 - 还有decorator 的概念 - 状态允许您映射不同的状态,并且您可以通过$stateParams 在状态之间轻松传递信息。 - 您可以通过$state 轻松确定您是否处于模板中的某个州或某个州的父级。
  • 我可以像ng-route一样使用otherwise({ redirectTo: '/404' });
  • 您可以使用它,但这会给用户一个错误的消息。因为 404 仅在找不到页面或我们尝试访问由于某些服务器相关问题而无法访问的页面时使用。 otherwise({ redirectTo: '/urlPath' }); 一般用于认证失败或url路径无效的情况。
猜你喜欢
  • 2014-05-27
  • 2012-05-18
  • 2015-05-19
  • 2013-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
相关资源
最近更新 更多