使用Amazon S3时如何将抓取工具请求重定向到预渲染页面?

时间:2015-09-07 00:01:44

标签: angularjs amazon-web-services amazon-s3 seo single-page-application

问题

我有一个使用Angular构建并在Amazon S3上托管的静态SPA网站。我试图让爬行器可以访问预呈现的页面,但我无法重定向爬虫请求,因为Amazon S3不提供URL重写选项,并且重定向规则有限。

我拥有什么

我已将以下元标记添加到 index.html 页面的<head>中:

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

此外,我的SPA使用漂亮的URL(没有散列#符号)和HTML5推送状态。

通过此设置,当抓取工具找到我的http://mywebsite.com/about链接时,它会向GET发出http://mywebsite.com/about?_escaped_fragment_=个请求。这是一个pattern defined by Google,后面是其他抓取工具。

我需要的是使用 about.html 文件的预呈现版本来回答此请求。我已经使用Phantom.js完成了这个预呈现,但我无法向抓取工具提供正确的文件,因为Amazon S3没有重写规则。

nginx 服务器中,解决方案是添加重写规则,如:

location / {
  if ($args ~ "_escaped_fragment_=") { 
    rewrite ^/(.*)$ /snapshots/$1.html break; 
  } 
} 

但是在Amazon S3中,我受到基于KeyPrefixes和HttpErrorCodes的redirect rules的限制。 ?_escaped_fragment_=不是KeyPrefix,因为它出现在URL的末尾,并且它不会出现HTTP错误,因为Angular会忽略它。

我尝试了什么

我开始尝试在ngRoute中使用动态模板,但后来我意识到我无法用任何Angular解决方案来解决这个问题,因为我的目标是无法执行JavaScript的抓取工具。

使用Amazon S3,我必须坚持使用重定向规则。

我已经成功地使用了一个丑陋的解决方法。如果我为每个页面创建一个新规则,我就完成了:

<RoutingRules>

  <!-- each page needs it own rule -->
  <RoutingRule>
    <Condition>
      <KeyPrefixEquals>about?_escaped_fragment_=</KeyPrefixEquals>
    </Condition>
    <Redirect>
      <HostName>mywebsite.com</HostName>
      <ReplaceKeyPrefixWith>snapshots/about.html</ReplaceKeyPrefixWith>
    </Redirect>
  </RoutingRule>

</RoutingRules>

正如您在此解决方案中所看到的,每个页面都需要自己的规则。由于亚马逊只限制了50个重定向规则,因此这不是一个可行的解决方案。

另一种解决方案是忘记漂亮的URL并使用hashbangs。有了这个,我的链接将是http://mywebsite.com/#!about,抓取工具会使用http://mywebsite.com/?_escaped_fragment_=about来请求此链接。由于URL将以?_escaped_fragment_=开头,因此可以使用KeyPrefix捕获它,只需一个重定向规则即可。但是,我不想使用丑陋的URL。

那么,我如何在Amazon S3中拥有静态SPA并且对SEO有利?

1 个答案:

答案 0 :(得分:6)

简答

Amazon S3(和Amazon CloudFront)不提供重写规则,只有有限的重定向选项。但是,您需要重定向或重写您的网址请求。只需预先呈现所有 HTML文件,然后按照您的网站路径上传

由于浏览网页的用户启用了JavaScript,因此将触发Angular并控制页面,从而导致重新呈现模板。有了这个,所有Angular功能都将可供该用户使用。

关于抓取工具,预渲染页面就足够了。


实施例

如果您的网站名为 www.myblog.com ,并且指向其他网页的链接 www.myblog.com/posts/my-first-post 。可能,您的Angular应用程序具有以下结构: index.html 文件位于根目录中并负责所有内容。页面 my-first-post 是位于 /partials/my-first-post.html 中的部分HTML文件。

这种情况下的解决方案是在部署时使用预渲染工具。您可以使用PhantomJS进行此操作,但由于您在Amazon S3中托管了静态网站,因此无法使用Prerender等中间件工具。

您需要使用此预渲染工具来创建两个文件: index.html my-first-post 。请注意, my-first-post 将是一个没有 .html 扩展名的HTML文件,但您需要将其Content-Type设置为 text / html < / strong>上传到Amazon S3时。

您可以将 index.html 文件放在根目录中,将 my-first-post 放在名为帖子的文件夹中,以匹配您的网址路径 / posts / my-first-post

使用这种方法,抓取工具将能够检索您的HTML文件,用户将乐于使用所有Angular功能。


注意:此解决方案要求使用根路径引用所有文件。如果您访问 www.myblog.com/posts/my-first-post 链接,相对路径将无效。

根据路径,我的意思是:

<script src="/js/myfile.js"></script>

使用相对路径的错误方法是:

<script src="js/myfile.js"></script>


编辑:

下面是我用来使用PhantomJS预呈现页面的一些小代码。安装PhantomJS并使用单个页面测试脚本后,在部署站点之前,在构建过程中添加一个脚本以预呈现所有页面。

var fs = require('fs');
var webPage = require('webpage');
var page = webPage.create();

// since this tool will run before your production deploy, 
// your target URL will be your dev/staging environment (localhost, in this example)
var path = 'pages/my-page';
var url = 'http://localhost/' + path;

page.open(url, function (status) {

  if (status != 'success')
    throw 'Error trying to prerender ' + url;

  var content = page.content;
  fs.write(path, content, 'w');

  console.log("The file was saved.");
  phantom.exit();
});

注意:它看起来像Node.js,但它不是。它必须使用Phantom可执行文件执行,而不是Node。