GitChat · 管理 | 前端小团队如何培养技术积累?

来自 GitChat 做者:ewind
更多IT技术分享,尽在微信公众号:GitChat 技术杂谈前端

引言

前端是个挺特别的岗位,一方面它的技术栈更新几乎是软件开发领域中最快的,但另外一方面它的不可替代性相对而言却并不算高。而且,虽然多数企业都有相对独立的前端团队,但团队多半都有很多业务负担,加上前端较高的迭代速度,一线业务同窗的成长多少容易遇到些瓶颈:需求都作不完了,还有时间读源码解析吗?ios

其实咱们都知道,我的成长和团队成长是分不开的。一方面在技术氛围较好的团队中我的的进步会更快,另外一方面团队的技术积累也是由一个个成员们贡献出来的。这就引出了咱们的问题:在业务团队中,有什么方法能让我的和团队在迭代中都获得更好的成长呢?git

能想到最简单的答案应该就是「按期技术分享」和「不加班,给你们更多的学习时间」这样的吧。不仅是前端,相信这确定也是广大开发同窗们喜闻乐见的。惋惜业务压力摆在那里,若是我的学习影响了短时间内的团队产出,那么老板们的脸色也许会有些微妙……从另外一个角度上来讲,前端同窗提高技能水平所需学习的各类模式、框架、类库、工具,在开源社区都有很是详尽的文档和教程,如何提高我的能力的话题也更不是本文所能覆盖的。不过,若是一个前端团队可以经过一些技术层面上的方式,培养出由团队成员共建的良好技术基础的话,相信老板们和开发同窗们均可以接受吧。这其实也正是本文所关注的。json

积累的方向

在介绍「怎么作」以前,咱们不妨考虑下「作什么」,即在什么方向上去培养技术积累呢?axios

全栈

咱们知道 Full Stack Developer 的概念一直很火,那么按照 Full Stack 的概念,前端团队的所需的技术积累是怎样的呢?这意味着前端团队须要横向地扩展本身的能力,拉通 DB 到 HTML 的流程。技术栈覆盖面广天然是好事,但是为何仍是常常可以听见对全栈的争议呢?在不少须要快速迭代实现原型的场合,这样的能力模型是很合适的。问题在于在一个系统的开发中,多数状况下团队成员负责开发的是独立的模块。而按照信息隐藏的理念,而只有在代码模块采用定义良好的接口来封装,模块的内部结构对外部不可见,复杂度被屏蔽而非暴露在他人模块内部结构前的时候,开发的效率才是最高的,也并非团队中全部成员都须要了解系统总体的技术细节。而且,前端自己也是对开发职能分工的细化,在后端有成熟稳定团队的前提下,前端在团队层面按照 Full Stack 的方向积累技术,在投入和产出上未必是最优的。固然,这和许多大厂「只招全栈」的理念并不矛盾,毕竟在我的开发者层面的全栈所真正要求的并非杂而全,而是高效地解决各种问题的学习能力,以及对技术更加全面的深刻。后端

全生命周期

在团队层面,和 Full Stack 相对的其实有一个 Full Life Cycle Engineer 的概念。这个理念实际上鼓励的是让前端同窗去更全面地参与产品的生命周期,并在生命周期的各个阶段去更好地支持业务。这个情景下从项目的原型中前端就会以提供 UI 组件的方式参与,在实现了具体需求后也会参与到测试和发布的流程中,而服务端渲染等特性也要求前端去支持起必定的运维职责。这种模式下,前端的职责并不只仅局限在传统的客户端 HTML + CSS + JS 中,而是一系列与用户交互相关的技术合集。这个背景下,能够把前端团队理解为一个垂直的功能性的团队,技术积累上也是更多地围绕着咱们所面对的业务问题去作沉淀。套用《人月神话》里外科手术式团队的概念,若是说全栈的角色更接近于全能的「外科医生」的话,那么 Full Life Cycle Engineer 则更接近于纵向深刻的「代码专家」。浏览器

围绕着这个理念展开,不难发现许多技术点是在团队层面上能够去作积累的。而具体到落地,就更须要鼓励团队同窗们来解决比常规业务开发更难的工(zao)程(lun)化(zi)问题了。前端轮子是公认的多,几乎全部常规开发所涉及的领域都存在很是多的现成轮子,那么是否有必要去积累团队内部的轮子,又在什么方向去作呢?这其实视团队状况不一样,是很是业务驱动的。好比,维护 C 端产品的团队,可能更须要性能优化、监测告警方向的轮子,而开发 B 端中后台产品的团队,对状态管理、统一组件库一类的轮子需求度则会更高。在深刻业务的过程当中,几乎总能找到特定的场景可以抽取出特定的复用模块,或找到适合针对性优化的地方,这其实就至关于技术积累的起点了:在业务驱动下开始造(甚至发明)团队内部的轮子性能优化

关于造轮子

其实造轮子对技术积累的促进,并不只仅体如今实现轮子这件事自己。好比,即使是一个很是简单的 UI 按钮,在将它实现为可复用的代码时,所须要作出的工程化努力均可以是很深度的。好比,即使一开始只在团队内部使用,API 设计得简单没有关系,但做为一个可复用的模块,怎么样让使用者不须要读源码就能用呢?这时候咱们须要最基本的文档;怎么样保证升级后 API 稳定呢?这时候单元测试就体现出了意义;发布为模块的话,样式怎样和组件一块儿提供呢?这时候须要的是构建流程……这些和基本业务逻辑并不直接相关的工程化内容,即使只是开发出一个简单的内部轮子时均可以渐进地去考虑和实现。而且,这些工程化的特性也正是作技术积累的良好切入点。若是编写的代码都是不须要复用的「一次性」代码,那么文档就是多余的;若是实现 UI 逻辑只是为了知足基本的业务须要,那么其实是没有什么机会和必要去将单元测试落地的;若是最终打出的包始终只是面向用户而非面向开发者,那么甚至也不须要考虑 dependencydevDependency 的区别…工做内容限制在一个狭窄的子集内的时候,成长显然是会受限的。微信

固然了,以上引入的工程化特性客观上都须要时间投入,也难免会有重复造轮子浪费人力之嫌。这时如何去作权衡和取舍呢?框架

动机和理由

咱们不妨评估一下引入新轮子的投入和产出。好比,分析一个没有积累公共组件或依赖第三方组件库的团队,是否有开源项目中未能提供的 UI 组件,这些组件是否有复用的可能性和条件呢?若是有的话,引入工程化的发布流程会带来多少时间成本,是否可以方便其余同窗在后续的使用中节约回来呢?再好比,是否存在业务场景是现有的开源轮子不能彻底符合需求的?若是本身动手,可以收获多少易用性或性能上的提高呢?毕竟造轮子也是工程,而工程问题老是能够评估、分析和 Tradeoff 的。

实际上,前端领域中,因为业务场景的多样性,开源轮子不能彻底匹配实际需求的状况是很常见的。好比,Redux 是个用来支持复杂应用的状态管理库,在增查改删的后台应用中使用起来十分沉重;实现不需考虑兼容的简单页面时,本身封装出的简单 DOM 操做库确定比 jQuery 或 Zepto 更加轻量;封装登陆认证库时若是所有交互都经过 JSONP,那么依赖 fetch polyfill 或 axios 的成本还不如直接实现……熟悉业务后,这样的场景老是容易发现的。

可是光有动机,并不能成为决策的充分理由。一个团队所面对的挑战更毫不仅仅只是造一两个轮子就可以解决的。这时候在团队层面,讨论出一份 Todo List 一般是颇有帮助的。咱们能够经过讨论,整理出一个团队目前须要所须要解决的技术问题的任务列表,并按照「是否重要,是否紧急」的四象限方法梳理出任务的优先级,再去根据列表中各个任务的重要、紧急程度,来决定如何安排团队的资源投入。毕竟不论轮子的设计是否简洁、代码是否优雅,只有可以更好地解决具体问题,可以更普遍地被业务所使用,造轮子才可以得到更多的产出。

如何启动

在决定了具体方向后,咱们就能够开始动手了。对于怎样实现业务逻辑,相信同窗们都已经颇有经验了。那么,怎样从头开始造一个轮子呢?这里面从 0 到 1 的过程和经验可能也是一些刚组建或者积累较少的小团队所较为欠缺的。

实际上,从 0 到 1 的过程,其实就至关于一个实现 Proof of Concept 的过程。一个 POC 原型只须要实现新轮子最核心的一两个特性就足够了,实现上并不须要考虑得大而全。而且,面向团队内部使用的轮子通常也具备较高的定制性,不须要过多地按照普适性解决方案来设计。在实现这样定制型较高的的模块时,一般可以带来设计上的简单性并更好地节约时间。这方面 SalesForce 的经验能够做为参考:在实现一个系统的时候,若是让各类流程和参数都充分地可定制,那么总体上开发所需工做量可达到简单实现的 2-3 倍。其实,在内部面向业务需求定制的组件若是追求灵活性很高的设计,那么 API 设计一般会更加复杂,从而使得每次在使用时也会相对地更加复杂(例如可以自由传入子组件的 React 组件,其复杂度和使用难度都比普通的组件要高很多),这时开发组件 + 使用组件的整体投入甚至有可能小于代码模块化的产出。更加可行的方法论是经过权衡实际业务场景,本着 KISS 原则去来保证明现上的简单性,同时轻微地在正确性、完整性和一致性上作一些让步,这样会更容易产出和维护可复用的模块。同时,许多工程化内容的落地难点实际也是工具引入上从 0 到 1 的一次性投入,例如在从 0 到 1 跑通第一个测试用例后,添加和完善用例的难度就小得多了。而且,实现这些特性的过程当中一般也可以接触到更新和更完善的工具链,将内部轮子中小规模运用并验证的的新特性再去逐步推广到业务项目中,也是实践中可行的方式。

维护与管理

然而,光有一两个由核心成员业余开发出的类库,并不必定可以促进团队总体的技术积累。在通常的模式下,可复用代码的开发一般会交给团队中经验相对丰富的同窗,而这些同窗自己极可能还有更重要的业务问题去解决,这时候即使有了一次性的产出,后续的维护和迭代也是一个问题。为此,咱们探索的模式更倾向于基于 Monorepo 的共建。什么是 Monorepo 呢?这是一个管理机构代码的方式。它摒弃了原先一个模块对应一个 Repo 的组织方式,而是将全部的模块都放在一个 Repo 中来管理,这也是目前 Babel / React / Angular / 等流行项目所应用的开发方式。早期的团队项目中每每会将各个模块仓库拆分管理,造成 Multirepo 的模式,这时对于各自独立的业务项目没有关系的,但对于复用的模块而言,这种模式主要会存在这样的一些问题:

  • Repo 与 Module 须要拆分、迁移或整合时维护上的困难,尤为在涉及交接时。
  • Issue 缺少集中的管理。
  • 模块间依赖形成版本发布时,对各个仓库手工维护 link / lint / test 时的繁琐操做。
  • 新同窗接手开发或维护时的较高复杂度。

而 Monorepo 的方式,则是将团队内积累的可复用模块整合至同一个仓库中来维护,这样在团队同窗有维护和改进的需求时,跑通环境然后 up and go 的流程会获得很大程度上的简化。以组件库为例,不一样组件之间可能会存在相互依赖,而 Monorepo 就在依赖配置上有更好的支持,也易于整合提供更完善的构建工具,简化发布的流程。这时,共建的模式就从「个别同窗做为上游承担全部需求」,转化为「提供一个完善了构建和测试的基本框架来实现共建」。团队成员能够根据业务状况抽取出公共组件整合至组件库内,这个开发新组件的过程相对于本身另起炉灶会更加简化,而且更重要的是在这个环节中,通常性业务开发中常常缺失的单元测试和 Review 是真正有机会去实施的,相对于对业务代码的 Review 常常因为进度问题而难以实施,在可复用组件的层面去作 Review 是更加有意义的。同时,内部的组件库对 bug 的响应也可以更加迅速,依据 SemVer 高效发布 patch 版本也可以更好地支持业务。在组件库使用范围为团队内部的前提下,组件库外部依赖过多形成业务方版本更新时出现问题的可能性也会小得多。

除开用于基本业务开发的组件库,Monorepo 里还可以根据实际的业务情景,装下许多应对团队其它需求的内容。好比,对于常常须要开发临时性小项目的团队,整合了内部服务的 boilerplate 脚手架就是一个很好的可复用模板。不过这里较为特殊的一点是,脚手架的配置通常须要暴露,且能够假设使用者熟悉相关的配置细节,在 Webpack 等工具的使用方式几乎已成为通用领域知识的前提下,对成熟工具进行二次封装的内部工具在学习成本和灵活性上比较容易遇到问题。这里咱们一方面能够保持组件库的小而美,另外一方面则能够结合 repo 中的其余复用模块,精简脚手架中的代码到其它模块中。通常在实际业务场景中,脚手架所整合、接入的一些内部服务很容易在不一样业务中暴露出一些问题,这时候使用脚手架的团队成员也很容易经过 PR 的形式将 bugfix 同步回原仓库,这个流程的参与门槛也并不高,但不能小看维护者增加对项目长期稳定性的帮助。做为一个小技巧,咱们不妨去除掉每一个源码文件中自动生成的 @author 注释,代之以在根目录中放置开源项目中常见的 CONTRIBUTOR / AUTHORS 文件或 package.json 中的 authors 字段,这里的关注点就从「背锅」转化为了「参与」。

实践经验

咱们的团队组建时间并不长,主要的业务场景是开发和维护较多的 PC 端业务系统,这里分享一点技术积累的产出来抛砖引玉吧?

脚手架

因为通常而言团队内部基本上都会但愿能使用统一的编码规范和技术栈,这时候脚手架实际上是一个很不错的切入点。脚手架也是咱们最先实现、业务使用最普遍、同时有最多同窗参与维护的轮子。看看国内前端社区铺天盖地的「xx + yy + zz 项目模板」就知道,实现一个脚手架的难度并不高,但就提高开发效率,节约团队同窗时间而言,它确实有在团队内部推广的价值。在开始阶段的脚手架其实就是一个 Koa + React / Redux 的 Webpack 模板,随着业务复杂度增长,脚手架中除了整合各类接入的服务外,还出现了愈来愈多的参数配置。在这个过程当中它开始逐渐变得沉重、不易上手。为了改善这个问题,咱们除了按照「如何配置以知足常见需求」的方式完善了文档外,还进行了登陆服务、代理服务的依赖化,将基础性的业务需求以 Koa 中间件的形式抽离以实现更好的复用。

咱们对脚手架自己的定位更偏向于项目起始的模板,而不是一套对 Webpack 的封装。实际上许多对 Grunt / Gulp / Webpack 等工具作二次封装定制出后的新工具,虽然在必定程度上可以更快地开发出原型,但在须要团队其它成员定制、维护时,团队成员对主流工具的使用经验难以应用到这些封装后的工具上,尤为在内部文档不够详尽的时候,这些定制的工具每每更加难以推广。所以,咱们在维护脚手架时,更加偏向于将 Webpack 的配置清晰地暴露给使用者,不在这里掺杂额外的 Magic。目前,团队过半同窗脚手架已经加入了脚手架的 AUTHORS 名单内,咱们但愿它可以做为一个长期的积累,获得持续的维护。

组件库

React 组件库是另外一个已有必定产出的团队积累项目。组件库的开发除了整合默认 UED 交互,知足业务需求外,更多地成为了一个新技术的试验田。组件库中落地了单元测试、Publish Hook 等质量保障的特性,也更多地尝试了新工具,更是首先引入了 Monorepo 的管理方式,贡献组件的流程也实现了自动化。目前虽然组件规模有限,但咱们一样以提高团队技术积累的愿景在持续维护。

固然了,团队中并非全部同窗都有时间和精力可以贡献新组件,维护组件库也不是强制性的要求。但对于没有参与实际组件开发的同窗,也并不是没有参与的方式。例如,每位同窗能够在本身负责的业务中使用组件库中的组件,反馈问题、提出 Issue,或者也能够交流、Review 组件的 API 设计。开源项目对 Issue 的响应通常在天级,而组内的扁平交流可以将组件 bugfix 更新的速度提升到小时级,对于业务迭代较快的团队,具有内部组件库的高效响应能力是颇有帮助的。

Node 服务

脚手架和组件库都是面向客户端 JavaScript 的技术,而在前端同窗须要对所负责的体验作更高程度的优化时,咱们的能力范围也须要拓展到 Node 服务端。虽然对于 Node 层的存在曾经有过必定的争议,但实践证实 Node 在性能上对于 Web 服务这样主要瓶颈在于 IO 的服务是足够的,而维护性上「回调地狱」也早已在语言机制的改进中获得了解决。目前对 Node 层的使用,主要目的而非深刻到后端所专一的数据接口中去替代后端,而是为了提升开发效率,解决前端服务部署与渲染的问题,提高前端在整个应用生命周期中的服务能力。在这种场景下,前端对 Node 的使用实际上是很轻量的,但做为 Web 服务,Node 端一样须要接入许多较为基础的服务,如性能、日志、监控、告警等。和浏览器端一言不合造轮子的方式不一样的是,这类内容多数已有成熟的服务,在 Node 端所需实现的主要也是一些接入服务所需的代码。一样地,这些内容也很适合在 Monorepo 中提供可供快速验证的 demo,或整合到团队的 boilerplate 项目中,提供从本地调试到线上部署的支持。这时共建的模式一样适用,而且在团队业务覆盖面较广时,许多服务的接入更可能首先来自于业务同窗,然后再整合至 Monorepo 中。这种模式也是很合适的。

总结

从先后端分离到 Node 出现,再到各种框架全家桶兴起,以及如今的服务端渲染和 PWA,近年来前端的技术发展确实至关快速,可谓「惟一不变的是变化自己」。本文中想要探索的其实也是前端团队在技术的演进中积累技术沉淀的若干一些小技巧和较为通常性的规律,但愿抛砖引玉能对有耐心读到这里的前端同窗们有所帮助 :-)


实录:《ewind:前端小团队如何培养技术积累实战解析》


彩蛋

【 做者招募 】

咱们 GitChat 通过半年的运营,在产品形态上不断改进。

此次,咱们将系统性的优化 GitChat 一些内容,在原有 Chat 基础上推出新的内容分享产品:

GitQ 精品课程

若是您在 IT 技术上有本身独到的学习心得 或 自成体系的技术成长套路,咱们很是期待您能在 GitQ 上进一步实现:

GitQ 定位:具有专业性、成体系的IT类课程
GitQ 形态:独家文章(6~12篇)+读者圈答疑
GitQ 订价:9.99 / 19.99 等

【做者如何开设 GitQ 精品课?】

提交以下内容:课程名称 / 用户定位 / 课程大纲
GitChat 进行内容评估与课程策划
双方肯定课程细节、交付时间
GitChat 完成课程的上线、宣传推广
【做者注意事项】

GitQ 精品课内的文章,在课程上线一年内属于 GitChat 独家使用。
按约定时间准时交付文章。
课程上线后,积极在读者圈回答用户的提问。
【更多咨询】
可在文末留言,或加微信联系 GitChat 主编:ztx415


图片描述

相关文章
相关标签/搜索