YUI3在美团

keynote下载 | pdf下载

Notes:

  1. 常荣幸和大家一起分享我们团队在YUI3方面的一些实践。

  2. 我叫尚春,他们都叫我春哥。这里是我的博客和email。我在2010年12月11日毕业后进入美团工作,到现在已有7个多月的工作经验。这段时间,在师傅的指导下迅速成长,对前端的认识不断深入。

  3. 此次分享主要涉及两方面的内容。首先是关于选择YUI3作为基础库的原因,这里我们重点介绍下YUI3的模块机制;然后我们主要就我们实际迁移中遇到的一些挑战作详细表述,例如划分模块、加载策略等。

  4. 简要介绍下我们的前端团队。我们是一支小而精悍的队伍,为美团网视觉界面和用户交互提供充足动力。

    • 我们崇尚的是“快”,通过快速开发、快速部署、快速迭代来完成任务、优化功能
    • 我们坚持“在行进中开火”
    • 我们认为做事不应该准备太多,一定要先做起来,然后发现不足并不断改进,宁可十年不将军,不可一日不拱卒

      这些信条可能更加适合我们这样的小团队。

  5. 我们首先要回答的问题是:为什么选择YUI3。第一个原因,我们原来采用的是YUI2。作为YUI团队的作品,YUI2非常正统、稳定。第二个原因,YUI团队已经把重心转移到YUI3,基本不再维护YUI2。但这都不是最有说服力的原因。

  6. 最为重要的原因是YUI3本身,它足够的优秀。YUI3具有很多新的特性,例如模块机制、选择器的全面应用、更强大的自定义事件、组件框架等等。如果说YUI2是库时代杰出典范之一的话,YUI3就是框架时代一颗璀璨的明星。

  7. 时间有限,我们重点介绍下YUI3的模块机制。模块是YUI3最大的变化,没有之一。这一底层设计机制改变了原有YUI2时代的规则。它为我们带来了自动加载、沙箱、combo等等特性,解放生产力的同时,提高了多人协作上的便利。使用YUI3添加模块、调用模块比较简单。

  8. 我们把源码进行适当简化,主要理解一下内部的机制。YUI构造器的add方法是这样定义的,即将模块的信息注册在YUI构造器的静态属性Env中。

  9. YUI的use方法主要流程是:计算调用模块所依赖的所有模块,将这些模块进行排序并输出,通过attach方法将这些模块的api依次捆绑在YUI实例(沙箱)上,将载满api的YUI实例传递到回调函数中。

  10. 与直接嵌入script标签相比,模块的特点有:

    • 注册模块与调用模块分离,两者不是紧密耦合关系
    • 所有模块都加载并绑定后才会执行回调函数,多个use间是异步关系。但,当所有模块都具备的情况下,多个use又是同步关系
    • 通过实例绑定调用模块的api,实现了一种简便的沙箱机制。这一机制有利于协同开发
    • 在模块定义时的一些元信息将所有模块有序组织起来,形成一个系统
  11. YUI3的所有模块分为四个层级,它们构成了YUI3的架构。

    • 最底层是种子文件YUI,它定义了YUI构造器以及yui模块,主要包括Lang,UA,封装的Array, Object, 以及Get等等
    • 第二层为核心工具层,主要是一些工具模块,例如DOM,Node,Event
    • 第三层为组件框架层,主要是为构建组件提供丰富灵活的机制
    • 第四层为组件层,包括了IO,JSON,Animation等重要模块
  12. 我们遇到很多挑战:

    • 如何将原来的功能划分为模块,如何将所有模块组织起来,这是比较大的一个挑战
    • Combo服务的实现。yahoo的combo只能提供YUI自身模块,而且速度在国内并不占优势。我们采用了minify,进行了一些修改和配置,能够在线上线下提供combo的支持
    • 模块加载策略的研究
    • 版本管理的问题。原来我们采用了query string的方式进行版本管理,现在则是用embedding的方式
  13. 目前,我们已经将大多数后台系统迁移到了YUI3。本季度我们要完成主站的迁移工作。

  14. 在介绍迁移之前,先看一下原来我们组织js的方式。这里主要包含三类文件:二次开发的核心文件core.js和一些widget文件,应用层级的文件,例如app-deal.js,来自第三方的文件,例如jquery.js。这种方式非常简单,但在web app时代已经不再适合较为复杂的前端开发,维护成本比较高。

  15. 那如何划分模块呢,我们总结了如下几条原则:

    • 抽象与应用必须脱离。更通用的功能应该放在更低的层级,应用层完全面向实际问题,在解决的过程中调用抽象出来的方法
    • 职责单一。保持每个模块的职责足够简单,方便维护和可持续开发
    • 粒度得当。有了combo,我们可以不必担心粒度太小,文件过多导致的速度问题。但是,从可维护的角度来考虑,粒度应该适当而不宜过小,避免海底捞针的情形出现
    • 我们的模块体系应该是开放的,不符合YUI规范的第三方模块,我们可以借鉴整合进来,使我们的基础框架更加完善,更加性感
  16. 美团的JS架构,按照抽象与应用程度,分为四层:

    • 最底层交给强悍的YUI3,为我们提供很跨浏览器的api和很好的框架
    • 第二层是我们二次开发的一些核心方法和控件库。mt-base中包含strtotime,getRadioValue等基础方法,对Cookie的简单操作,一些封装的页面动画等。w-base,w-autocomplete等包含一些封装的控件,提供更加高效的用户体验,且便于后端人员调用
    • 第三层包含美团各个分站点的一些通用模块。例如mis-base包含后台mis系统的消息系统、checkFormChanged等通用方法。这一层更加接近应用
    • 最上面一层,应用模块,这些模块的方法都是用来解决实际问题的。例如mis-deal用来处理mis系统中所有deal相关页面的交互,finance-pay用来处理财务系统中的付款相关页面的交互。一些零碎的应用方法我们放在对应站点的misc模块中
  17. 为了保持向前兼容,我们定义了新的全局对象M。我们对YUI进行了简单的封装,可以使用M.add添加模块,使用M.use调用模块。请注意,每次使用M.use都会新生成一个config的实例,这个config信息主要包含一些combo服务器信息,我们自己开发模块的信息。这样loader就知道该如何计算依赖的模块了。在对use的封装中,我们还引入了debug的功能。[代码演示]

  18. 目前我们采用的加载方式是:预加载通用基础模块,例如yui,node,event,io等,然后是站点级别的一些操作,例如mis系统的widget初始化、消息系统初始化等,最后是页面级别的一个特定应用入口。

  19. 我们对基于PHP loader的服务器端loader进行了尝试,并准备近期进行部署。

    服务器端loader优势在于速度,同时,将其整合在框架中降低了维护成本,简便易用。

  20. 通过使用服务器端loader,可以做到一次性加载。

Proudly powered by Express. Designed by Spring.