探讨webapp的SEO难题(上)
前言
.net解决思路
<script type="text/blade_config">
{
url: 'restful/index',
template: 'indexTmpt'
}
</script>
<script id="indexTmpt" type="text/blade_template">
<ul>
<% for(var i = 0, len = data.length; i < len; i++) { %>
<li><%=data[i].name %></li>
<% } %>
</ul>
</script>
//模拟数据返回
data = [
{id: 0, name: 'item_0'},
{id: 1, name: 'item_1'},
{id: 2, name: 'item_2'}
]
这里期待的webapp处理逻辑:
期待的seo处理逻辑:
为什么不直接服务器吐出完整html?
这个方案的代价是:
.net解析javascript
① 解析页面的config信息,取出url以及template
② 根据url发出请求返回数据,这里由于是局域网应该很快
③ 解析template,根据data生成静态html
④ 其它处理,返回客户端
模拟处理逻辑
我们这里略去url请求一步,假设数据已经返回,否则这里又要写.net程序
var data = [
{id: 0, name: 'item_0'},
{id: 1, name: 'item_1'},
{id: 2, name: 'item_2'}
];
这里的模板字符串为:
var template = [
'<ul>',
'<% for(var i = 0, len = data.length; i < len; i++) { %>',
'<li><%=data[i].name %></li>',
'<% } %>',
'</ul>'
].join('');
然后我们要做的就是解析这个模板,生成对应的模板解析函数,这里是调试代码:
var data = [
{ id: 0, name: 'item_0' },
{ id: 1, name: 'item_1' },
{ id: 2, name: 'item_2' }
]; var template = [
'<ul>',
'<% for(var i = 0, len = data.length; i < len; i++) { %>',
'<li><%=data[i].name %></li>',
'<% } %>',
'</ul>'
].join(''); var templateHandler = function (text, data) { var noMatch = /(.)^/; var escapes = {
"'": "'",
'\\': '\\',
'\r': 'r',
'\n': 'n',
'\t': 't',
'\u2028': 'u2028',
'\u2029': 'u2029'
}; var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; var templateSettings = {
evaluate: /<%([\s\S]+?)%>/g,
interpolate: /<%=([\s\S]+?)%>/g,
escape: /<%-([\s\S]+?)%>/g
}; var render;
settings = templateSettings;
var matcher = new RegExp([
(settings.escape || noMatch).source,
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
].join('|') + '|$', 'g'); var index = 0;
var source = "__p+='";
text.replace(matcher, function (match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset)
.replace(escaper, function (match) { return '\\' + escapes[match]; }); if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':escape(__t))+\n'";
}
if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
}
if (evaluate) {
source += "';\n" + evaluate + "\n__p+='";
}
index = offset + match.length;
return match;
});
source += "';\n"; if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" +
source + "return __p;\n"; return source; try {
render = new Function(settings.variable || 'obj', source);
} catch (e) {
e.source = source;
throw e;
} if (data) return render(data);
var template = function (data) {
return render.call(this, data);
}; template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; return template;
} templateHandler(template, data)
首次调试爆了很多错误,而且服务器端的调试比较费力,错了只能靠经验去猜测
这里返回的是需要构造成函数的字符串,但是我们看到我们的“ul”等标签被吃掉了!!!
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='';
for(var i = 0, len = data.length; i < len; i++) {
__p+=''+
((__t=(data[i].name ))==null?'':__t)+
'';
}
__p+='';
}
return __p;
我们这里一旦调用就抛了一个错误,这个时候一般是模板或者传入数据出错了,可惜的是他是对其中一段语法不可解析!这里从侧面反映出一个问题:
该方法若是模板出错会导致程序无法运行,如果是node的话很可能就crash了!
PS:这里由于CLR4解析javascript的时候字符串的replace遇到正则时有问题,在此逗留3小时,这里把我搞惨了,定位就很久最后还得重写模板解析!!!
var data = [
{ id: 0, name: 'item_0' },
{ id: 1, name: 'item_1' },
{ id: 2, name: 'item_2' }
]; var template = [
'<ul>',
'<% for(var i = 0, len = data.length; i < len; i++) { %>',
'<li><%=data[i].name %></li>',
'<% } %>',
'</ul>'
].join(''); var templateHandler = function (text, data) { var noMatch = /(.)^/; var escapes = {
"'": "'",
'\\': '\\',
'\r': 'r',
'\n': 'n',
'\t': 't',
'\u2028': 'u2028',
'\u2029': 'u2029'
}; var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; var templateSettings = {
evaluate: /<%([\s\S]+?)%>/g,
interpolate: /<%=([\s\S]+?)%>/g
}; var render;
var settings = templateSettings; var matcher = new RegExp([
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
].join('|') + '|$', 'g'); var index = 0;
var source = "__p+='";
var _text = text; var _treg; while (1) { var matcher = new RegExp([
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
].join('|') + '|$', 'g'); (function () {
_treg = matcher.exec(_text)
})(); var t_str = _treg[0];
var t_len = t_str.length;
var t_index = _treg.index; source += _text.slice(index, t_index).replace(escaper, function (match) { return '\\' + escapes[match]; });
_text = _text.slice(t_index + t_len); if (_treg[2]) {
source += "';\n" + _treg[2] + "\n__p+='";
}
if (_treg[1]) {
source += "'+\n" + _treg[1] + "\n'";
}
if (_text.length == 0) break; }
source += "';\n"; if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" +
source + "return __p;\n"; try {
render = new Function(settings.variable || 'obj', source);
} catch (e) {
e.source = source;
throw e;
} //return source; if (data) return render(data);
var template = function (data) {
return render.call(this, data);
}; template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; return template;
} templateHandler(template, { data: data })
正确的代码
我这里使用生命在调试啊!!!因为服务器解析javascript时候,很多东西都不支持,感觉有点回到了c++!!!
小结
这里字符串解析成功,我们这部分也就告一段落了,本身.net方案也不是这次的重点,这里提供基本思路各位自己去看看吧,总之调试很坑
下期预告
对javascript来说,nodeJS自然是亲爹,我们这次的主要方案其实是基于nodeJS的,这里的期望:
① 用户请求过来时候首先判断是否为网络爬虫
② 网络爬虫访问seo/index.html,用户访问webapp/index.html
当然,我们做demo时候不会这么麻烦,我们直接为其添加一个seo=true的标志位在url即可
nodeJS实现SEO的方案重点依旧在首屏渲染,我们这里首先基于blade做两个页面,然后以此扩展seo的方案
当然此块内容有点小复杂,加之,小钗对nodeJS停留在学习阶段,这块需要学习,而且最近有些其它事情扰心,暂时便搁置了
这块的内容可能与RapidJS(clouda前身)有关,有兴趣的同学可以先去看看
文中有误请您指出,若您对webapp的seo有什么好的想法请留言
探讨webapp的SEO难题(上)的更多相关文章
- DTCMS添加文章,将tags标签的值赋到SEO关键词上,以及将摘要的值赋到SEO描述
将tags标签的值赋到SEO关键词上 admin\article_edit.aspx中 $(function () { 方法中加上 //tags的值赋到SEO关键词上 $("#txtTag ...
- SEO优化上首页之搜索引擎排名规则
搜索引擎建立索引的网页数以万亿计,用户搜索的关键词也是海量,如果每个用户提交搜索请求后,搜索引擎都去数以万亿的索引中重新排名网页,效率将非常低下.根据2-8法则,80%是查询是集中在相同的20%内容上 ...
- SEO优化上首页之搜索引擎原理内容处理与索引
上文<搜索引擎原理SEO优化上首页之蜘蛛Spider>详细介绍了蜘蛛的分类.抓取入口.抓取策略和更新策略.搜索引擎已把页面抓取回来,接下来是解析页面内容,主要包含判断页面类型.提取页面主题 ...
- SEO优化上首页之搜索引擎蜘蛛Spider原理
Spider,蜘蛛,又名网页网络爬虫.网络机器人,是按照一定策略不断抓取互联网网页的特定程序.蜘蛛抓回的页面创建索引后参与排名,等待用户检索.为了网站优化自然排名上首页,精灵儿工作室下面详细剖析Spi ...
- SEO优化上首页之搜索引擎原理简要
搜索引擎(Search Engine)是特定的计算机程序,它根据一定的策略.从互联网上搜集信息,对信息进行处理后,为用户提供检索服务,并将用户结果展示给用户. 搜索引擎优化(Search Engine ...
- SEO优化上首页之搜索引擎作弊案例与反作弊原理
搜索引擎流量价值巨大,有不少人专门研究排名机制,利用搜索引擎漏洞作弊,寻求快速提高网站排名,进而获取更多的流量和利益,甚至有的网站优化公司专门提供作弊服务.搜索引擎为了杜绝这种情况,必须能过滤大量垃圾 ...
- SEO优化上首页之搜索引擎用户需求理解
经过前面<搜索引擎原理SEO优化上首页之网络蜘蛛Spider>和<搜索引擎原理SEO优化上首页之内容处理与创建索引>介绍,搜索引擎已经完成页面抓取和分析,并把原始页面.索引等信 ...
- Safari配置WebApp----添加启动图和桌面图标让你的WebApp在ios设备上体验如原生一样
现在很多开发者的Web应用程序的设计样式和交互类似本机应用程序,例如,它的缩放比例适合iOS上的整个屏幕.当用户将其添加到主屏幕时,您可以通过使其看起来像本机应用程序一样,在iOS上为您的Web应用程 ...
- #翻译# 深入JavaScript的Unicode难题(上)
退一步说, JavaScript处理Unicode时有些怪异. 这篇文章会说明JS在Unicode上令人痛苦的部分, 然后提供解决方案, 并说明在未来的ECMAScript6中是如何改善这些问题的. ...
随机推荐
- WPF DatePicker只显示年和月 修改:可以只显示年
最近的项目,查询时只需要年和月,不需要日,因此需要对原有的DatePicker进行修改,查询了网上的内容,最终从一篇帖子里看到了添加附加属性的方法,地址是http://stackoverflow.co ...
- 了解HTML锚点
概念 <a>元素 (或HTML锚元素, Anchor Element)通常用来表示一个锚点/链接.但严格来说,<a>元素不是一个链接,而是超文本锚点,可以链接到一个新文件.用i ...
- Dijkstra算法优先队列实现与Bellman_Ford队列实现的理解
/* Dijkstra算法用优先队列来实现,实现了每一条边最多遍历一次. 要知道,我们从队列头部找到的都是到 已经"建好树"的最短距离以及该节点编号, 并由该节点去更新 树根 到其 ...
- ASP.NET MVC Authorization 自定义跳转
应用场景:在 ASP.NET MVC 应用程序中,需要对用户身份权限进行验证,比如没有登录或者不符合权限的用户,访问 Action 的时候,跳转到指定页面. 重写 Authorize: public ...
- 将Excel文件转换为Html
将Excel文件转换为HTML 背景 我的工作有时会涉及到财务数据的处理.我们大家都知道,Excel文件在处理数据中很流行并且被广泛使用.Excel让我们可以将存储在里面的数据进行数学计算.我在工作中 ...
- ios多线程-GCD基本用法
ios中多线程有三种,NSTread, NSOperation,GCD 这篇就讲讲GCD的基本用法 平时比较多使用和看到的是: dispatch_async(dispatch_get_global_q ...
- C语言 第五章 循环结构
一.for 请在屏幕上输出1000个*号 printf("*************************...."); #include "stdio.h" ...
- ubuntu super daemon设置
super daemon是一个在Linux下面全面管理自己服务设置的东东,他可以接管很多服务的设定,只需要在/etc/xinetd.d/下面放置好自己的配置文件就可以了,那么,具体应该怎么配置呢? ...
- RMAN Catalog创建、配置和管理
环境:RHEL6.4 + Oracle 11.2.0.4 一.创建数据库catdb 1.1 官档的建库脚本示例 1.2 根据我实际环境修改如下项 1.3 创建必要目录并赋予权限 1.4 执行脚本建库 ...
- 仿优酷Android客户端图片左右滑动(自动滑动)
最终效果: 页面布局main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayou ...