之前和朋友们讨论过 Angular 的 SEO 的问题,后来在测试一个叫 angular-scafford 的 gem 的时候发现他的这个机制很有趣,不知道能否解决这个问题。
后面的内容从我的 blog 直接搬运了,原地址 http://textlearn.org/blogs/96。
前提之一是服务端渲染的页面 layout 和 Angular 的 index 页面通用,例如:
<html>
<head>
<link href="http://test.css" media="screen" rel="stylesheet">
<script type="text/javascript" src="angular.js"></script>
<script type="text/javascript" src="angular-resource.js"></script>
<head>
<body>
<div ng-view>
.................
</div>
<body>
</html>
/*服务端的模板和Angular的模板都加载在省略号的地方。*/
还需要的是在 angular 的路由中添加 $locationProvider.html5Mode true
,来去除#符号,让 Angular 的 route 和服务端的 route 能够对应起来。
然后我们就可以正常编写服务端和 angular 的代码,当一个客户端 http 请求发送过来时,我们会返回给他服务端渲染的代码。加载页面的同时,angular-resource 这个插件会向服务端再发送一条 content-type=json 的请求。
一旦获取了 json 数据,angular 就开始执行代码,将......处原先将要加载的服务端渲染文档替换成 angular 生成的内容 (前提是前面提到的服务端和 angular 共用同一个 layout)。此时我们查看网页源代码,会发现只有一组 json 数据。因为查看源代码显示的是最近的一次请求得到的数据。
而如果刷新查看源代码这一页,由于查看源代码页只是发送一条对 html 的请求,而并不会执行 html 中的 js,因此刷新后就可以得到服务端渲染出的页面了。
也就是说,我们看到的内容和 js 能否执行是有关系的。如果 angular.js 能够执行,我们将看到 angular 的内容,整个网站相当于单页应用,除了刷新和第一次请求外,客户端和服务端的交互都是通过 json 来实现,如果不能,则看到的是服务端渲染的内容。
这样在兼容性方面也可以做到 IE9 以下用户走服务端渲染的页面,其它用户则走 angular 的逻辑。
如果是简单的 curl 地址,或者一些无法执行 js 的网络爬虫,无疑会抓取到服务端渲染的内容。不过对于百度和 Google 的抓取机制我就不清楚了,无法确定能否收录。