整站ajax化

整站ajax化(简称ajaxifying)亦即使用ajax渲染网页的主要部分,通过极大程度减少冗余的请求来提升网站速度,它有别于我们平时所理解的较小区域的异步刷新, ajaxifying使页面上绝大部分的内容是通过ajax完成渲染,这样的处理需要额外考虑这些大容量内容渲染的效率,内容模块化管理等因素。

Ajaxifying网站需要把每个页面中相同和不同的部分分开来,相同的部分比如一些固定的菜单,网站的整体框架,一些聊天窗口等,而用户会来回切换的是的每个页面间的差异内容,而这些是正ajaxifying要处理的内容。

Gmail是较早成功利用ajaxifying来提升使用体验的产品,最近在这方面做得相对好的应该是Facebook,在去年的O’Reilly Velocity China 2010大会上Facebook的Changhao Jiang博士介绍的Facebook在性能优化上做的几件大事让我印象深刻,其中之一就是Facebook大范围使用ajaxifying极大程度优化了网站性能。

重视在WPO(Web Performance Optimization)上的关注和投入,可以为网站带来跟好的体验以及更多的用户,并且可以一定程度上降低成本,虽然很多性能优化的技术已经相对透明,但是对于如何创新利用、合理组合这些技术上,还是要根据每个网站的实际情况量身定做,Aliexpress(Alibaba的在线B2B2C交易平台)卖家营销中心最近在性能优化上也进行了不少尝试,其中最值得介绍的是我们也在这个平台上也使用了ajaxifying,期待能为用户提供更舒畅的使用体验。

Ajaxifying对于网站好处主要在于:

  • 极大减少冗余数据的反复请求而提升网站性能
  • 保存基本一致的浏览体验的前提下提供类客户端软件的使用体验

 

我们的Ajaxifying实现方案在架构上提供了以下几个基础功能和组件:

  • 兼容主流浏览器的历史记录管理
  • 静态资源的依赖管理、异步加载器
  • 供开发人员使用的模块管理器
  • 内容缓存机制
  • 内存管理机制

 

历史记录管理

Ajaxifying网站需要保持与普通跨页浏览基本一致的浏览体验,由于ajax的局部刷新特性不支持浏览器历史访问记录,因此需要通过配合浏览器hash来实现统一的体验。主流浏览器都可以记录hash的变化作为访问历史,在hash改变的时候会触发一个hash变化的事件,通过这个触发源我们的程序就可以捕捉到当前的hash值进行后续处理。

由于IE6,IE7不支持hash变化事件,需要额外使用一个iframe来保存历史记录。

异步渲染和资源动态加载

异步加载器是ajaxifying的核心部件,用于加载需要渲染的内容和异步加载的脚本、样式,加载的方式有通过jsonp直接在返回的脚本中渲染,通过跨子域ajax请求获取需要渲染的json对象,然后再客户端再进行渲染,这两种方式有利有弊,jsonp更适合在不同域名的情况下使用。

为了避免重复造轮子,我们的脚本加载器选择的是requireJS,它是一个开源的模块化脚本加载器,在模块化上的处理正好能符合我们的设计,其他的脚本加载器还有headJS,LABjs,controlJs等。

模块化管理

考虑ajaxifying整站的时候需要对网站的业务有充分的了解,在此之上对这些业务进行合理的分类,一般来说可以把每个主菜单当成一个一级模块,每个模块都有一个对应的hash值与之对应,当用户的hash改变成为某个值的时候,模块管理器就会去搜寻匹配出这个模块,并且从模块的信息中获取这个模块渲染数据的来源和渲染的区域等信息,所以用户看到的url会是这样:http://channel.alibaba.com/wsscore/index.htm#product

在我们的设计中实现了模块数的设计,每个模块都可以有无限层级的子模块,这样设计的目的是让用户可以在刷新当前页面之后依然能够回到刚才访问的内容,ajaxifying框架会根据hash值中体现的层级关系来依次载入每个层级上的模块数据,访问二级子模块的时候url为:http://channel.alibaba.com/wsscore/index.htm#product/myItems

模块化地设计可以让开发人员简单地进行配置即可进行开发,所有我觉得facebook所提出的Link Controler在处理hash和模块的匹配上显得过于臃肿了,后续的维护成本也会不断增加,而我们的方案采用的是对hash进行嗅探的机制,只要直接把每个可能触发内容重新渲染的链接改成对应的模块名称,整个网站即可工作。

内容缓存

在用户浏览的内容之中可能会存在许多不需要每次访问都更新的内容,这些内容如果一次获取之后就不需要在每次都重复去请求,对这些内容进行缓存可以节省很多在获取这些数据上的时间,不过需要注意的时候缓存的内容如果有特定的时机需要更新,你就要提供更新的机制,并且缓存内容如果不加控制,缺乏良性管理很可能会造成内存泄露,程度严重的话会直接影响用户体验,所以我们还需要一个内容管理机制。

内存管理

这里所说的内存管理,并不是针对我们的js代码之中需要注意的细节,而是ajaxifying网站后由于长期不刷新,许多js变量和缓存的数据不断累积,最终会导致客户端不堪重负而降低网站响应速度。所有我们在设计方案的时候考虑了为每个模块添加一个内存回收的过程,

不过这个回收如果运作需要开发人员自定去完成,所以对于开发人员对于该模块的设计要有较深的理解。

由于整站ajax对于SEO效果有一定的影响,ajaxifying在你不了解实现方式的情况下并不适合用于需要考虑SEO影响的网站使用。

Ajaxifying需要在细节上综合考虑每个方面的实现,不契合业务的设计往往会让后续的扩展束手缚脚,而不合理的设计也会使开发人员浪费许多不必要的精力,aliexpress为卖家营销中心所使用的Ajaxifying方案设计了一个综合以上部件的整站ajax化框架,现在还在不断地完善之中,在更多的实践和改进之后会跟大家见面。

Published by

Z.J.T

Product Designer from Wandou Labs

  • http://www.swordair.com/blog 葵中剑

    从头看到尾,感觉看了一本没有产品的介绍说明书。

    • http://fordifferent.com Z.J.T

      我自己也这么感觉,码字功力差,其实这本身仅仅是介绍一个方案,并没有真正的产品。

  • http://yang-feng.org 杨峰

    说的好。虽然是个产品说明。