我有一个使用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有利?
答案 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。