我看到AngularJS应用程序关于搜索引擎和SEO的两个问题:

1)自定义标签会发生什么?搜索引擎会忽略这些标签中的全部内容吗?例如,假设我有

<custom>
  <h1>Hey, this title is important</h1>
</custom>

<h1>是否在自定义标记中被索引?

2)有没有办法避免搜索引擎索引{{}}绑定字面上?即。

<h2>{{title}}</h2>

我知道我可以做点什么

<h2 ng-bind="title"></h2>

但是如果我真的想让爬虫“看到”标题呢?服务器端渲染是唯一的解决方案吗?


当前回答

谷歌的可爬行Ajax规范,在这里的其他答案中引用,基本上是答案。

如果你对其他搜索引擎和社交机器人如何处理同样的问题感兴趣,我在这里写了最新的技术:http://blog.ajaxsnapshots.com/2013/11/googles-crawlable-ajax-specification.html

我在一家https://ajaxsnapshots.com公司工作,该公司将可爬行Ajax规范作为一种服务来实现——报告中的信息是基于我们对日志的观察。

其他回答

使用像PreRender这样的东西,它可以创建站点的静态页面,这样搜索引擎就可以索引它。

你可以在这里找到它适用于哪些平台:https://prerender.io/documentation/install-middleware#asp-net

让我们来明确AngularJS和SEO

谷歌、雅虎、必应和其他搜索引擎使用传统的爬行器以传统的方式爬行网络。他们运行机器人抓取网页上的HTML,在此过程中收集信息。他们保留有趣的单词,并寻找到其他页面的其他链接(这些链接,它们的数量和数量将与SEO发挥作用)。

那么为什么搜索引擎不处理javascript网站呢?

答案与搜索引擎机器人通过无头浏览器工作的事实有关,它们通常没有javascript渲染引擎来渲染页面的javascript。这适用于大多数页面,因为大多数静态页面并不关心JavaScript是否呈现其页面,因为它们的内容已经可用。

对此我们能做些什么呢?

幸运的是,大型站点的爬虫程序已经开始实现一种机制,允许我们使JavaScript站点可爬行,但这需要我们对站点进行更改。

如果我们将hashPrefix改为#!而不是简单的#,那么现代搜索引擎将更改请求使用_escaped_fragment_而不是#!(在HTML5模式下,即我们没有哈希前缀的链接,我们可以通过查看后端的User Agent头来实现相同的功能)。

也就是说,不是来自普通浏览器的请求,看起来像:

http://www.ng-newsletter.com/ !/注册页面

搜索引擎将使用以下方法搜索页面:

http://www.ng-newsletter.com/?_escaped_fragment_=/signup/page

我们可以使用ngRoute的内置方法来设置Angular应用的哈希前缀:

angular.module('myApp', [])
.config(['$location', function($location) {
  $location.hashPrefix('!');
}]);

并且,如果我们使用html5Mode,我们需要使用meta标签来实现这个:

<meta name="fragment" content="!">

提醒,我们可以用$location服务设置html5Mode():

angular.module('myApp', [])
.config(['$location', 
function($location) {
  $location.html5Mode(true);
}]);

处理搜索引擎

我们有很多机会来决定如何以静态HTML的形式将内容实际交付给搜索引擎。我们可以自己托管后端,我们可以使用服务托管后端,我们可以使用代理来交付内容,等等。让我们来看看一些选择:

自托管

We can write a service to handle dealing with crawling our own site using a headless browser, like phantomjs or zombiejs, taking a snapshot of the page with rendered data and storing it as HTML. Whenever we see the query string ?_escaped_fragment_ in a search request, we can deliver the static HTML snapshot we took of the page instead of the pre-rendered page through only JS. This requires us to have a backend that delivers our pages with conditional logic in the middle. We can use something like prerender.io's backend as a starting point to run this ourselves. Of course, we still need to handle the proxying and the snippet handling, but it's a good start.

通过付费服务

将内容导入搜索引擎最简单、最快的方法是使用服务Brombone、seo.js、seo4ajax和prerender。IO是其中的一个很好的例子,它将为您提供上面的内容呈现。当我们不想处理运行服务器/代理时,这是一个很好的选择。而且,它通常非常快。

要了解更多关于Angular和SEO的信息,我们在http://www.ng-newsletter.com/posts/serious-angular-seo.html上写了一个关于它的广泛教程,我们在我们的书ng-book: The Complete book on AngularJS中更详细地介绍了它。请登录n-book.com查看。

With Angular Universal, you can generate landing pages for the app that look like the complete app and then load your Angular app behind it. Angular Universal generates pure HTML means no-javascript pages in server-side and serve them to users without delaying. So you can deal with any crawler, bot and user (who already have low cpu and network speed).Then you can redirect them by links/buttons to your actual angular app that already loaded behind it. This solution is recommended by official site. -More info about SEO and Angular Universal-

Angular自己的网站为搜索引擎提供简化的内容:http://docs.angularjs.org/?_escaped_fragment_=/tutorial/step_09

假设你的Angular应用正在使用一个Node.js/ express驱动的JSON api,比如/api/path/to/resource。也许您可以使用?_escaped_fragment_将任何请求重定向到/api/path/to/resource.html,并使用内容协商来呈现内容的HTML模板,而不是返回JSON数据。

唯一的问题是,你的Angular路由需要与你的REST API 1:1匹配。

编辑:我意识到这有可能真正搅乱你的REST api,我不建议在非常简单的用例之外使用它,在那里它可能是一个自然的适合。

相反,您可以为机器人友好的内容使用完全不同的路由和控制器集。但是你在Node/Express中复制了所有AngularJS的路由和控制器。

我决定用无头浏览器生成快照,尽管我觉得这有点不太理想。

(2022)尽可能使用服务器端渲染,并使用Pushstate生成url

谷歌现在可以运行JavaScript,所以很可能只使用JavaScript构建一个网站,只要你创建一个合理的URL结构。然而,页面速度已经成为一个越来越重要的排名因素,通常客户端构建的页面在初始渲染时表现不佳。

服务器端呈现(SSR)可以帮助您在服务器上预先生成页面。你的html包含将被用作页面根的div,但这不是一个空的div,它包含JavaScript将生成的html,如果它被允许运行。

客户端下载HTML并渲染它,给出一个非常快速的初始加载,然后执行JavaScript,用生成的内容替换根div的内容,这个过程称为水合作用。

许多新的框架都内置了SSR,尤其是NextJS。

(2015)使用PushState和Precomposition

目前(2015年)的方法是使用JavaScript的pushState方法。

PushState在不重新加载页面的情况下更改浏览器顶部栏中的URL。假设您有一个包含选项卡的页面。选项卡隐藏和显示内容,内容是动态插入的,可以使用AJAX,也可以简单地设置display:none和display:block来隐藏和显示正确的选项卡内容。

当单击选项卡时,使用pushState更新地址栏中的URL。呈现页面时,使用地址栏中的值确定要显示哪个选项卡。Angular的路由会自动为你做这件事。

Precomposition

有两种方法可以点击推送状态单页应用(SPA)

通过PushState,用户点击一个PushState链接,内容就被ajax化了。 通过直接点击URL。

在网站上的初始点击将包括直接点击URL。当PushState更新URL时,后续的点击将简单地在内容中加入AJAX。

爬虫从页面中获取链接,然后将它们添加到队列中以供后续处理。这意味着对于爬虫来说,服务器上的每一次点击都是直接点击,它们不通过Pushstate导航。

预组合将初始有效负载捆绑到来自服务器的第一个响应中,可能是作为JSON对象。这允许搜索引擎在不执行AJAX调用的情况下呈现页面。

有一些证据表明谷歌可能不会执行AJAX请求。更多信息请点击这里:

https://web.archive.org/web/20160318211223/http://www.analog-ni.co/precomposing-a-spa-may-become-the-holy-grail-to-seo

搜索引擎可以读取和执行JavaScript

谷歌已经能够解析JavaScript有一段时间了,这就是为什么他们最初开发了Chrome,作为谷歌蜘蛛的全功能无头浏览器。如果一个链接有一个有效的href属性,新的URL可以被索引。没什么可做的了。

如果另外点击一个链接触发一个pushState调用,用户可以通过pushState来导航站点。

搜索引擎支持PushState url

推送状态目前由谷歌和必应支持。

谷歌

以下是Matt Cutts对Paul Irish关于PushState在SEO方面的问题的回答:

http://youtu.be/yiAF9VdvRPw

下面是谷歌宣布对蜘蛛的完全JavaScript支持:

http://googlewebmastercentral.blogspot.de/2014/05/understanding-web-pages-better.html

结果是谷歌支持PushState并将索引PushState url。

参见谷歌网站管理员工具的fetch as Googlebot。你会看到你的JavaScript(包括Angular)被执行了。

Bing

以下是必应在2013年3月宣布支持漂亮的PushState url:

http://blogs.bing.com/webmaster/2013/03/21/search-engine-optimization-best-practices-for-ajax-urls/

不要使用hashbang #!

Hashbang url是一种丑陋的权宜之计,要求开发人员在特定位置提供网站的预渲染版本。它们仍然有效,但你不需要使用它们。

Hashbang url是这样的:

domain.example / # !/ /资源路径

这将与一个像这样的元标签配对:

<meta name="fragment" content="!" >

谷歌不会以这种形式对它们进行索引,而是从escaped_fragments URL中提取站点的静态版本并对其进行索引。

Pushstate URL看起来像任何普通的URL:

domain.example /道路/ /资源

不同之处在于,Angular会通过拦截对文档的更改来为你处理它们。location用JavaScript处理它。

如果你想使用PushState url(你可能会这样做),去掉所有旧的散列样式的url和元标签,在配置块中启用HTML5模式。

测试你的网站

谷歌网站管理员工具现在包含一个工具,它将允许您获取谷歌的URL,并呈现JavaScript作为谷歌呈现它。

https://www.google.com/webmasters/tools/googlebot-fetch

在Angular中生成PushState url

要在Angular中生成真实的url,而不是带有#前缀的url,请在$locationProvider对象上设置HTML5模式。

$locationProvider.html5Mode(true);

服务器端

由于您使用的是真实url,因此需要确保服务器为所有有效url提供相同的模板(加上一些预先组合的内容)。如何做到这一点取决于您的服务器架构。

网站地图

你的应用程序可能会使用不寻常的导航形式,例如悬停或滚动。为了确保谷歌能够驱动你的应用程序,我可能会建议创建一个站点地图,一个你的应用程序响应的所有url的简单列表。你可以把它放在默认位置(/sitemap或/sitemap.xml),或者使用网站管理员工具告诉谷歌。

无论如何,有一个站点地图是个好主意。

浏览器支持

Pushstate在IE10中工作。在旧的浏览器中,Angular会自动退回到哈希样式的url

演示页面

下面的内容是使用预合成的推送状态URL渲染的:

http://html5.gingerhost.com/london

正如可以验证的那样,在这个链接中,内容被编入索引,并出现在谷歌中。

提供404和301报头状态码

因为搜索引擎总是会为每个请求访问您的服务器,所以您可以从服务器提供报头状态代码,并期望谷歌看到它们。