IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    手机百度前端工程化之路:前端js模块库

    三水清 (ksky521@gmail.com)发表于 2014-08-02 16:47:07
    love 0

    即上篇文章《手机百度前端工程化之路》,接下来会写几篇文章详细介绍下提到的具体方案,本文介绍:前端js模块库。

    目标

    • 重复代码抽离
    • 模块间依赖关系明确
    • 方便静态资源管理

    误入歧途

    刚开始想给项目做个js基础库的时候,正值手机一个重要版本开发,遇见的问题是引入了zepto.js作为基础库之后,页面性能急剧下降,滑动页面都很卡顿,经过排查发现是zepto默认绑定了一个window的scroll事件导致。

    于是想,为什么不自己重造个轮子?而且zepto也不过短短千行代码而已!

    说干就干,当自己实现了一些基础函数(此部分就是后来Bdbox库的core部分)和Ajax之后,发现没有什么可以写的了。原因如下:

    • 选择器直接使用document.querySelector*系足矣
    • 事件绑定直接使用 addEventlistener 足矣
    • ajax部分已经写完了
    • DOM操作和class操作部分,手写即可

    于是跟组里宣布:大家都是用Bdbox吧!

    但是问题接踵而至,团队成员隔段时间就来找我:为什么没有zepto的xx功能?于是我就实现了xx功能,如此一两天时间内,我实现了:

    • class操作函数
    • event类函数,包括delegate函数
    • 简单的DOM操作类函数

    经过这一两天的折腾,似乎明白了:我们组需要的是一个zepto,Bdbox不是一个基础库!其实这个跟团队的开发效率和整体技术能力有关系。在手机百度大版本的排期中,团队成员都追求开发效率,而使用Bdbox显然不如zepto上手容易,于是第一次尝试失败!

    选择第三方库的条件

    其实我早在一条微博说过用第三方库的前提,不仅仅是一个js基础库,比如对于backbone、angular这里大型库也要遵循。千万不要以炫技或者赶潮流而选择一个团队掌控不了的库。

    所以一般选择第三方库考虑的情况是:

    • 选择的第三方库,社区是否活跃,生态建设是否完善
    • 团队是否可以cover住bug
    • 扩展性,模块间耦合程度,模块可拔插性
    • 模块支持”私人订制“

    最终方案:zepto订制版 + AMD库Bdbox

    • zepto
      • dom操作,事件,ajax(单独模块)
      • 去掉不常用的模块
    • Bdbox
      • 手机百度js模块库,跟zepto互补
      • 实现业务常用模块
      • 做前端静态资源管理的基石

    Bdbox模块库

    进入正题,Bdbox模块库,采用AMD规范,模块依赖管理和模块异步加载部分使用php来实现,大大减小了核心代码:core.js的体积。编写时,实际采用的是commonjs规范,利用编译阶段给模块包裹define外表。

    值得一提的是,Bdbox的模块,注释很详细,结合jsdoc可以导出一份高大上的开发文档。

    说明 包含模块
    端能力 跟客户端相关 ios,android,apad,invoke,moplus,lbs
    通用&方案 通信、事件、跨域、SPA io,event,app,template,Deffered {:.highlight}
    工具 粒度小,用途广泛 utils,cookie
    性能&监控 用户行为统计、速度监控和错误收集 monitor,S,cache(ls/接口/静态资源)
    交互 页面交互相关,zepto扩展 Dialog,mask,swipe,fastclick
    运营 抽奖游戏,pv和行为统计,跨域通信,游戏类 刮刮乐,摇一摇,跑马灯,舞台/精灵/对象池/easing

    18个大类,50+个模块,覆盖手机百度所有应用场景

    模块管理方案

    前面提到了,Bdbox的core没有实现异步加载和依赖管理,而是通过php实现的。

    通过编译过程输出模块关系表

    这里不得不提下模块上线前的编译过程。

    1. 使用FIS编译,在postprocessor阶段包裹上AMD规范的define外层
    2. 在postpackager阶段,获取js文件内容,写入map.json(map.json会包含依赖关系)
    3. FIS编译结束,将 map.json 换成 config.php

    config.php就是一份完整的模块依赖关系表,其中还包括了模块的代码内容。

    利用php实现模块依赖管理

    当页面使用某一个模块时,php读取config.php文件,遍历模块依赖,优先将依赖的模块输出,从而保证模块定义时,依赖的模块都已经defined!

    利用config.php实现combo和inline

    config.php包含内容包括:

    • 模块id
    • 模块release后的url地址
    • 模块的代码内容

    所以,通过修改smarty的html标签,增加了rendermode属性,支持:tag、inline和combo三种渲染模式。

    • 当tag时,会依次输出script:src=release url标签
    • 当inline时,会依次输出模块代码内容
    • 当combo时,会合并release url,实现http请求的合并

    这样可以根据网络类型适配合适的渲染模式,并且方便代码debug。

    总结

    看上去实现很简单,但是效果确实杠杠的~ 下篇介绍下js模板的组件化管理



沪ICP备19023445号-2号
友情链接