本文为8月4日,『前端之巅』群『滴滴公共FE团队技术开放月』第一场分享活动总结整理而成,转载请注明来自『前端之巅』公众号。
张耀春,滴滴公共前端团队负责人,2009年接触前端,5年多博客撰写经历。国内较早接触Node.js,2013年开始应用React、Angular、Polymer到业务组件中,2014年曾参与翻译《Professional Node.js》一书。最近探索和应用的新技术:rollup、riot、vue等,领导团队一起钻研新技术的书籍预计于今年8月底出版。
作为公司级的公共前端团队,应该如何对团队进行定位,在实践过程中应注意哪些问题,如何打造这样的团队?本文对滴滴公共前端团队的实践进行了总结,希望能带给读者一些启发。
滴滴公共前端(FE)团队现在有十多个小伙伴,男女比例为 1: 1
。
作为公司级公共前端团队,滴滴公共FE团队的实践主要从以下几方面进行:
(1) 全局类: ①公司统一权限登录移动化和PC改版;②移动端用户统一登录SDK。
(2) 可视化方向: 滴滴国内央视曝光10多次春运迁徙可视化。
(3) 组件化方向: 公司级组件库——魔方。
(4) 通用服务: ①TMS运营和模板平台;②NPM Private。
(5) 用户类: ①微信等渠道内嵌的WebApp首页;②端内钱包支付等统一界面相关;③最近上线的安全行程分享;④H5前端服务化的项目:如滴滴捐献里程活动。
(1)努力成为公司业务线上的前端开发人员所信赖的伙伴、公司业务强有力支撑的前端技术团队。
(2)对前端业内有一定贡献的团队。
滴滴公共FE团队做的实践还是很多的,现列举几个比较重大且应用度广的实践。
魔方主要为了解决的痛点是:每一个系统UI、交互规范、组件技术都不一样,复用性低,依赖第三方开源但技术支持不到位,遇到问题没人服务。
为了解决问题,我们通过以下途径,综合考虑,开发了魔方。
以下是魔方的截图,可以通过这些截图,看到魔方所提供的主要服务。
魔方所用到的技术,包括以下几点:
由于PC我们全部依托Angular指令来编写,在WebPack采用了 ngtemplate-loader
。
不同环境两套配置文件:
webpack.config.js // 开发环境 webpack.min.js // 生产环境打包
区别:
//webpack.min.js output: { path: __dirname + '/dist/mofang-widget/' + version, filename: '[name].min.js', library: 'mofang', libraryTarget: 'umd' },
我们打包之后的目录:
dist/mofang-widget/0.1.1/mofang-widget.min.js
如何配置第三方依赖:
resolve: { root: path.join(__dirname, 'src'), alias: { components: path.join(__dirname, 'src', 'components'), vendor_a: path.join(__dirname, 'src', 'vendor'), ui_bootstrap_a: path.join(__dirname, 'src', 'vendor', 'angular-ui-bootstrap'), ui_select_a: path.join(__dirname, 'src', 'vendor', 'angular-ui-select'), resource_a: path.join(__dirname, 'src', 'vendor', 'angular-resource'), sanitize_a: path.join(__dirname, 'src', 'vendor', 'angular-sanitize') } }
如何处理directory里面的template:
// 目录结构 components didi-list didi-list.html didi-list.js
// bn-list.js var templateListUrl = require('./bn-list.html'); // 指令代码: { templateUrl: templateListUrl }
module: { loaders: [ { test: //.html$/, loader: 'ngtemplate!html' } ] }
整体我们依赖pkg.json的version:
var version = require('./package.json').version; // 方案一: plugins: [ new webpack.DefinePlugin({ __VERSION__: JSON.stringify(version) }) ] // 方案二: callbackLoader: { getVersion: function () { return "'" + version + "'"; } }
关于iOS 9 Safari iframe src with scheme not working:
具体可以参阅: http://stackoverflow.com/questions/31891777/ios-9-safari-iframe-src-with-custom-url-scheme-not-working
WebPack 动态加载:
require.ensure([], function (require) { var qqmap = require('./qq/qqmap'); callback && callback(qqmap); }, 'qqmap'); require.ensure([], function (require) { var alimap = require('./ali/alimap'); callback && callback(alimap); }, 'alimap');
TMS为了解决的痛点如下:
我们采取了以下途径:
我们采用更定制化的Nodejs服务框架(从Sailsjs参考了很多)+mongo+pm2,结合公司发布系统、定制日志监控和脚本化运维规范。
详细的架构如下图所示。
(点击放大图像)
我们的DNode系统里面,默认支持2个配置文件。
config/env/dev.js config/env/prod.js
// config/env/dev.js { port: 1234 } // config/env/prod.js { port: 8000 }
启动服务的时候,控制参数:
默认走的是dev的所有配置。
dnode app.js --prod
这样默认就执行了所有prod的配置参数。
整体我们还是依托公司的发布系统,设置后置脚本来部署和安装部分依赖。
build.sh --- 部分安装,配置等 control.sh --- 提供一些方法来控制服务,启动 pm2 的参数和日志路径等 * `./control.sh start`:启动服务,如果服务已经启动会报错。 * `./control.sh restart`:重启服务,要求服务已经启动才能正确执行。 * `./control.sh reload`:优雅重启服务,要求服务已经启动才能正确执行。 * `./control.sh stop`:停止服务
设置固定的日志,依托公司统一日志监控,设置拉取策略和一些采集匹配规则。
在DNode里面我们所有的请求都会安装配置的middleware数组顺序,进行流转。这样的优势在于,我们可以在一开始设置一些requestTimer的监控middleware。
首先我们检查request头是:
if (req.is('multipart/form-data')) { }
然后我们会通过 formidable
的2个方法:
var formObj = new formidable.IncomingForm({ uploadDir: uploadPath, keepExtensions: true, multiples: false }); formObj.parse(req, function(err, fields, files) { // 这里面我们可以 check file.type 来对不同类型的文件进行不一样的处理: // 比如 css 文件: if (files.file.type == 'text/css') { minCssCode = new CleanCss().minify(cssCode).styles; } // 比如 js 文件: if (files.file.type == 'text/javascript') { minJsCode = UglifyJS.minify(jsCode, {fromString: true}).code; } // 比如 zip 文件: if (files.file.type == 'application/zip' || files.file.type == 'application/octet-stream') { } }
我们这边采用的是 skipper
在bodyParser的middleware里面做了一次过滤。
随着业务发展,随之配套的各种MIS运营、管控、数据可视化系统,业务需求紧急、前端同学人力投入大、联调效率低。
前端同学依赖的构建工具和编辑器各异,有时候初始化开发环境都需要1~2天。
Nodejs+数据存储+各种配置系统+脚本。
滴滴早期WebApp首页是由业务线同学维护,与业务线有一定程度耦合,新业务线接入相对比较困难,会暂用业务线同学本身已有的开发任务。
滴滴早期的登录每个业务线都会做一套,有开发成本。不利于账号部门收敛和管理各业务线账号,不利于做一些账号安全和组件升级;登录没有打通,新业务线或运营活动接入登录成本高。
前端项目越来越多,内部产出的工具包也比较多,如何自建一个私有库。
这个问题其实我每天都在思考,好像一直没有太明确的答案,这里也只是分享一些我个人的见解:
下面我从几个方面具体来谈一谈。
团队永远和人有关系,下面我从几个简单的维度,通过我对几个游戏的理解来分享一下我认为公共团队的人所需要的气质。
敢于超越,专业性要求高:赛车手和我们一般的开车的同学相比:更专业、对车子的熟悉度更高、追求超越和不愿意被超越。我很多时候推荐团建都是去玩室内卡丁车,而且每次都发现:有一些同学愿意最后和一些跑圈快的一组再比一轮,即使最后,那可能也是其他圈里面最快的。
能够沉浸在技术里面,去思考问题,最终产出:乐高一般有几千块零散的拼图、需要沉下心来、而且在脑海中大概有一个架子,不断地去尝试和调整,最终完成一个作品时候,你会很自豪。
敢于挑战自己惧怕的东西,克服困难,战胜自己:潜水是我开始最惧怕的一项运动,很早前我不会游泳,但我又渴望翱翔大海,在一段比较长的震痛期后,我完成了浮浅和深浅,看到了很多常人看不到的美丽景色:大海龟、大鲸鲨、暴风鱼群等。
沟通和沉淀才能让知识更记忆深刻:我自己喜欢翻译和写一写技术总结的文章,已经成为生活中一个不可或缺的习惯。然后再分享出来,得到一些批评和反馈。
作为团队负责人,其实我的压力还是比较大的,除了满足业务需求外,你更多还需要告诉团队方向在哪里、我们的计划是否是可以落地的。所以我会制定一些计划来提高个人的水平。
我自身也折腾过各种机器和环境部署、数据库,也接触过后端和安卓开发,在研究跨端体验的时候,花了两个月看了iOS相关的基础书籍和代码。
很多时候解决方案的合理性和全局观,不只是你熟悉业务就可以了,我更倾向让团队的很多同学熟悉前端独立部署、如何和不同的端交互以及他们内部相关的技术组成。而且大部分时候不敢于技术革新的一个很大原因:不了解、不熟悉、没把握。
很多时候时间确实是不够用的,而且有时候会参加很多会议和培训等。我管理时间一般的方式如下:
团队技术的提高离不开学习和应用新技术,最近新技术的落地有以下几点:
在很多时候,永远需要一个带头人跑的快一点,积极一点,在技术上鼓励创新和不断打磨沉淀优化,鼓励团队的小伙伴通过一些工具和技术手段来解决一些重复性的事情。
除了利用 合理、稳定、高效
的技术解决方案来服务日常的业务支撑外,考虑到前端技术的日新月异,我们也沉淀和创造一个统一的技术氛围:
公共FE团队在任何一个大公司都离不开业务线小伙伴的支持和厚爱、领导的认可和关注。
滴滴公共FE团队的发展,离不开所有给予我们帮助和信任的朋友,也离不开团队每一位亲爱的小伙伴的努力工作。
一路同行,只因为有你们:huangyi、wangjing、wangjin、suwei、shumei、xiaoqi、yanfen、miaodian、cuijing、yufei、huan总。
『前端之巅』群『滴滴公共FE团队技术开放月』分享活动预告:第二期:WebApp实践经验分享;第三期:公司级组件库以及MIS系统的技术实践分享。
感谢韩婷对本文的审校。
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ,@丁晓昀),微信(微信号: InfoQChina )关注我们。