我有一个使用Angular构建并在Amazon S3上托管的静态SPA站点.我正在尝试使爬网程序可以访问预呈现的页面,但由于Amazon S3不提供URL重写选项且重定向规则有限,因此我无法重定向爬网程序请求.
是)我有的
我已将以下元标记添加到< head>我的index.html页面:
<Meta name="fragment" content="!">
此外,我的SPA使用漂亮的URL(没有哈希#符号)和HTML5推送状态.
通过此设置,当抓取工具找到我的http://mywebsite.com/about链接时,它会向http://mywebsite.com/about?_escaped_fragment_=发出GET请求.这是一个pattern defined by Google,其次是其他爬虫.
我需要的是使用about.html文件的预渲染版本来回答此请求.我已经使用Phantom.js完成了这个预渲染,但我无法向抓取工具提供正确的文件,因为Amazon S3没有重写规则.
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并使用hashbang.有了这个,我的链接将是http://mywebsite.com/#!about,爬虫将通过http://mywebsite.com/?_escaped_fragment_=about请求此链接.由于URL将以?_escaped_fragment_ =开头,因此可以使用KeyPrefix捕获它,只需一个重定向规则即可.但是,我不想使用丑陋的URL.
那么,我如何在Amazon S3中拥有静态SPA并且对SEO友好?
Amazon S3(和Amazon CloudFront)不提供重写规则,只有有限的重定向选项.但是,您无需重定向或重写URL请求.只需预渲染所有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,但不能使用像Prerender这样的中间件工具,因为您在Amazon S3中托管了一个静态站点.
您需要使用此预渲染工具来创建两个文件:index.html和my-first-post.请注意,my-first-post将是一个没有.html扩展名的HTML文件,但是当您上传到Amazon S3时,您需要将其Content-Type设置为text / html.
您将index.html文件放在根目录中,将my-first-post放在名为posts的文件夹中,以匹配您的URL路径/ 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>
编辑:
下面是一个小的JavaScript代码,我用它来使用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执行.