{"action":"created","issue":{"url":"https://api.github.com/repos/my-fe/wiki/issues/1","labels_url":"https://api.github.com/repos/my-fe/wiki/issues/1/labels{/name}","comments_url":"https://api.github.com/repos/my-fe/wiki/issues/1/comments","events_url":"https://api.github.com/repos/my-fe/wiki/issues/1/events","html_url":"https://github.com/my-fe/wiki/issues/1","id":112779652,"number":1,"title":"百度母婴技术团队—基于Reactjs实现webapp","user":{"login":"my-fe","id":15227832,"avatar_url":"https://avatars.githubusercontent.com/u/15227832?v=3","gravatar_id":"","url":"https://api.github.com/users/my-fe","html_url":"https://github.com/my-fe","followers_url":"https://api.github.com/users/my-fe/followers","following_url":"https://api.github.com/users/my-fe/following{/other_user}","gists_url":"https://api.github.com/users/my-fe/gists{/gist_id}","starred_url":"https://api.github.com/users/my-fe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/my-fe/subscriptions","organizations_url":"https://api.github.com/users/my-fe/orgs","repos_url":"https://api.github.com/users/my-fe/repos","events_url":"https://api.github.com/users/my-fe/events{/privacy}","received_events_url":"https://api.github.com/users/my-fe/received_events","type":"Organization","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":74,"created_at":"2015-10-22T11:08:09Z","updated_at":"2015-12-30T02:03:40Z","closed_at":null,"body":"由于最近的reactjs实在太火，而且距离第一版已经快2年的时间了，已经相对稳定和成熟了，基于这两个前提下，团队对reactjs及其他开源技术进行了相关调研，发现落地是可行的，我们有4名前端同学，从调研到上线，大概花了1个半月的时间，期间有踩一些坑，后面会说，整个开发总体来说是非常顺利的，下面进入正题~~\r\n\r\n\r\n### 产品简介\r\n线上应用：mami.baidu.com\r\n\r\n我们做的是一个移动端的单页webapp，可以在这个h5页面完成商品选择->支付->订单跟踪整个闭环\r\n\r\n![image](https://cloud.githubusercontent.com/assets/15227832/10684224/2aa86bb6-797d-11e5-94ad-4268c8b3bf30.png)\r\n\r\n### 技术选型\r\n\r\n![image](https://cloud.githubusercontent.com/assets/15227832/10684959/0657af3e-7986-11e5-92b7-c4b9164c0add.png)\r\n\r\n\r\n### Reactjs\r\n\r\nReact.js是Facebook在2013年开源的一个JS框架，在目前的前端开发的主流模式MVC和MVVM中，React主要专注于View层的开发，即视图部分。\r\n\r\n使用React开发的好处有以下几点：\r\n\r\n1.\tReact倡导组件化的开发模式，这样的开发模式和客户端开发(iOS和Android)的模式很类似。这样就可以实现组件最大限度的复用；\r\n2.\tReact只负责视图部分的开发，很容易和其他已有的框架进行融合，例如Backbone和Angular，可以比较轻松的融入之前的项目中；\r\n3.\tReact通过virtual-dom和dom-diff的技术，避免了频繁操作DOM带来的性能损耗，开发的应用很流畅；\r\n4.\tReact通过virtual-dom实现了同构JS，这样一来前后端可以使用一套模板，节省了传统开发模式中要在前后端两套模板的时间；\r\n5.\tReact自从开源以来，获得了前端社区的广泛关注和好评，先前比较主流的库都针对React实现了相应的版本，在开发过程中有非常多的组件可以使用，避免了重复造轮子的困扰；\r\n\r\n基于以上几个优点，在本次项目中我们选择了React.js作为前端开发的框架。\r\n\r\n项目中实际是使用下来reactjs有2点留下了深刻的印象:\r\n \r\n* 规范：遵守W3C规范，基于web component的组件化开发模式，可读性和可维护性都和传统开发不可同日而语(这个很重要，因为市面上的很多框架都是自行一套的接口风格，群雄割据的时代已经快要结束，现在的框架如果不遵守w3c规范，自己意淫一套，开发者初次上手体验会很差) \r\n\r\n* 性能：操作虚拟Dom的速度React具有绝对的优势相对于传统web开发\r\n \r\n\r\n### Redux\r\nredux是一个优秀的前端框架，用于管理web应用中的整个数据流。 \r\n\r\n![image](https://cloud.githubusercontent.com/assets/15227832/10684964/128ac700-7986-11e5-882a-06451fd7ef11.png)\r\n\r\n\r\nreact只是MVC中的V层，在一个大型webapp中，以一种合理的形式来组织、维护不同来源的数据非常重要，我们希望在整个应用正确动态更新演变的同时，能够有清晰的代码结构、方便不同开发者分工协作、较低的维护成本。\r\n\r\nredux是flux多种实现的一个升级版，具有以下几个特征：\r\n\r\n1. 整个应用的状态(state)存储为一个对象. 单一数据源使得client端可以直接使用server端构建的单一对象，方便对当前状态的获取，同时使得调试简单。\r\n\r\n2. 极强的数据流约束。redux数据流的变化只能由action触发，由reducer产生新的state，并且state只读，代码结构一致、清晰，并且不同的层不会有重复代码。\r\n\r\n3. 完善的state拆分整合机制。 将state分为不同数据块，每一块分别维护自己的action以及reducer，这使得逻辑清晰，并且分工协作便捷。\r\n\r\n4. 强大的开发调试工具。webpack的hotload以及redux-devtools，使得调试方便，开发效率大大提高。\r\n\r\n5. 服务端渲染。与客户端相比，服务端生成一个state对象并返回给页面，就可在server和client实现同构的渲染。   \r\n\r\n6. 无复杂对象，action与reducer分别为纯JavaScript对象和函数，观念清晰，无复杂对象的学习、维护成本。\r\n\r\n7. 功能完善，文档清晰。 强大的中间件机制以及丰富的开源中间件库，使得redux功能更加完善，如何发异步请求、异步数据流如何处理都有规定以及清晰的文档。\r\n\r\n8. react-redux使得redux与react结合更顺畅。\r\n\r\n以上几个特征在母婴项目中也得到了很好的体现，redux是做单页web应用很好的选择。\r\n\r\n### nodejs\r\n我们基于团队内的一个nodejs的mvc框架`Lark.js`，实现前后端分离，这个框架已经开源，\r\n\r\n> Lark.js 是一个面向大并发大流量互联网服务的工业级 Node.js 框架[ 1 ]。它是从一个 10亿级以上 pv 的线上node.js服务抽象出来的一个通用框架，这里需要注意的是，lark.js 并不是为快速开发设计的框架。lark.js 在设计上采用了路由，分层架构等拆分很细的设计，并且没有像 django 或 ror 一样自己实现一整套完整系统。这些不是lark.js 的重点关注目标。lark.js 的目标是支撑大流量大并发的业务，性能、多人开发模式、架构和可维护性是关注重点。\r\n\r\nlarkjs作为一个可支撑大流量并发业务的nodejs框架，在性能、多人开发模式、架构以及可维护性方面值得推荐。目前larkjs已在百度多个产品线落地使用，大家有兴趣的话，可以[点击查看](https://github.com/larkjs/lark)，下面这两个图我们整个项目的目录结构和分层架构:\r\n\r\n![image](https://cloud.githubusercontent.com/assets/15227832/10685012/b3dc3634-7986-11e5-85ba-05297fe45caf.png)\r\n\r\n![image](https://cloud.githubusercontent.com/assets/15227832/10685018/e628db9c-7986-11e5-93bc-2dc1f0b871fd.png)\r\n\r\n### React-router\r\n\r\nreact-router作为webapp的路由模块，提供了丰富的功能，调用非常简单，react-router对pushstate支持很好，视图切换可以直接p-ajax\r\n\r\n![image](https://cloud.githubusercontent.com/assets/15227832/10684971/273e4e10-7986-11e5-9785-03c2240157bf.png)\r\n\r\n\r\n### 编译部署\r\n基于gulp和webpack，实现了一套编译工具，主要有两个命令，`npm run dev`和`npm run deploy`\r\n\r\n* dev：监听所有文件变化，基于babel将es6编译成es5，基于webpack区分出lib.js(lib.js是底层代码,这个文件几乎是不变的)和app.js(这个是业务代码每次上线都会根据需求变化)，编译less，并重启nodejs服务\r\n* deploy：主要是合并压缩js、css，并将这些静态资源文件md5打包，方便浏览器缓存\r\n\r\n![image](https://cloud.githubusercontent.com/assets/15227832/10664019/63d05844-78f2-11e5-9f83-8307c5ee41f7.png)\r\n\r\n\r\n### 问题和踩坑\r\n\r\n* state需要在做项目之前设计好，保证一份业务数据在state tree中出现一次\r\n* smart组件太少导致state需要逐级下传。\r\n* onClick事件在大部分安卓手机上不可点\r\n\r\n### 总结\r\n\r\n百度妈咪特卖项目在技术选型上选取了前端领域最热门的框架组合，项目成功落地后，对使用这一技术实现的优缺点总结如下：\r\n优点：\r\n1. 通过服务端以及前端的技术选型，实现了前端后同构。 同一套react组件分别在前后端render，避免了白页loading态的出现。\r\n2. 基于reactjs实现，除组件化、虚拟DOM在复用以及性能上带来的一般好处外，reactjs思想使得开发者之间更好的分工与合作，在配合上非常顺畅。\r\n3. react+redux，规范的接口以及极强的约束，使得整个代码结构清晰，不同开发者的代码高度一致。\r\n4. 技术生态。越来越多的开发调试工具以及JavaScript框架正在依附着react生长，这一技术选型对以后的产品升级以及客户端的开发上线打下了良好的基础。\r\n5.如果你想基于react-native开发native项目，也需要学习reactjs\r\n\r\n缺点：\r\n1.学习成本略高。如果想基于reactjs开发项目，还得学习redux、react-router、es6等一系列比较前沿的技术。\r\n2. 体积略大。这套技术实现，框架库代码压缩后大于200K,gzip后实际传输大小为60K+，更适合大型的webapp。"},"comment":{"url":"https://api.github.com/repos/my-fe/wiki/issues/comments/167917388","html_url":"https://github.com/my-fe/wiki/issues/1#issuecomment-167917388","issue_url":"https://api.github.com/repos/my-fe/wiki/issues/1","id":167917388,"user":{"login":"wtz","id":3872124,"avatar_url":"https://avatars.githubusercontent.com/u/3872124?v=3","gravatar_id":"","url":"https://api.github.com/users/wtz","html_url":"https://github.com/wtz","followers_url":"https://api.github.com/users/wtz/followers","following_url":"https://api.github.com/users/wtz/following{/other_user}","gists_url":"https://api.github.com/users/wtz/gists{/gist_id}","starred_url":"https://api.github.com/users/wtz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wtz/subscriptions","organizations_url":"https://api.github.com/users/wtz/orgs","repos_url":"https://api.github.com/users/wtz/repos","events_url":"https://api.github.com/users/wtz/events{/privacy}","received_events_url":"https://api.github.com/users/wtz/received_events","type":"User","site_admin":false},"created_at":"2015-12-30T02:03:40Z","updated_at":"2015-12-30T02:03:40Z","body":"你这个项目有用到异步Promise库吗"}}