我前段时间参与了一个react为主的大前端项目,覆盖Web、Android、Ios三个平台。由于整个业务逻辑侧重在手机端,且Web端也是到了项目中期才开始启动,我在搭底层框架时就没有考虑用类似react-native-web这样的框架把三端统一,而是分别以react-native和react为主起了两个项目来应对。

由于无论哪一端,调用的后端微服务集群都是同一个,导致两个项目中还是不可避免的出现了一些重复逻辑,我尝试了封装成npm包来重用逻辑,但仅限于那些通用且变化较少工具类代码,对于变化频繁的业务逻辑代码,封装出来的npm包时不时就要更新版本,且抽出到项目之外也不易开发和调试,用起来格外麻烦,得不偿失。

最近尝试了lerna,惊喜的发现它不但能解决当时项目的痛点,还能额外带来一些多项目管理相关的好处。

引入lerna

lerna的名字来源于希腊神话中的九头蛇海德拉(Lernaean Hydra),拿它形容多项目工程是再贴切不过了。

lerna的引入比想象中简单,其实,与其说引入lerna,倒不如说是导入到lerna更合适,因为具体的做法是通过命令行创建了一个新的lerna项目,然后把所有项目导入进去。而且在导入的同时,每个项目的git提交记录也都合并在了一起。

lerna initlerna import 你本地的项目路径

每个被导入的项目都会被存放在根路径的packages目录下,下面是我demo项目的截图,一共引入了三个子项目,分别是:rntest, web-app, shared。

使用lerna来管理项目依赖

引入lerna后,第一件事就是要处理安装依赖的问题,我们需要用lerna add 命令来代替我们习惯的npm或yarn,比如说现在给截图中的rntest项目安装lodash,就要执行下面的命令,该命令的底层实现也还是调用哦npm install之类的命令。

lerna add lodash --scope=rntest

不过,执行后你会发现其他项目中package-lock.json都发生了变化,让人非常困惑,这背后的原因是跟添加依赖后自动执行的安装命令lerna bootstrap有关。

lerna的依赖提升

lerna可以通过lerna bootstrap一行命令安装所有子项目的依赖包,而且在安装依赖时还有依赖提升功能,所谓“依赖提升”,就是把所有项目npm依赖文件都提升到根目录下,这样能避免相同依赖包在不同项目安装多次。比如多个项目都用了redux,通过依赖提升,只需要下载一次放到根目录的node_modules目录下,就可供其他所有项目来使用。不过,需要额外的参数--hoist让依赖提升生效。

lerna bootstrap --hoist

但是自动执行lerna bootstrap命令是不带依赖提升参数的,这就导致上面每个项目的lock文件都会被修改的原因。

当然,要解决这个问题也容易,可以通过lerna的配置来避免npm对lock文件的修改即可,写法如下:

yarn是lerna的最佳搭档

lerna默认使用npm作为安装依赖包工具,但也可以选择其他工具。yarn在1.0版本之后提供了workspaces的功能,该功能从更底层的地方提供了依赖提升,做的事情跟lerna如出一辙。把它跟lerna放在一起看,简直就像是为lerna量身定做一样。因此,推荐在lerna中搭配yarn一起使用。

把npm替换成yarn只需在lerna的配置文件添加两行代码即可,配置完以后立刻顺畅百倍。

高效的代码重用

在我参与的这个大前端项目里,多端之间代码重复的部分包含redux中的业务逻辑、http请求的处理、代码规范工具的检查、git钩子中的自定义脚本等等。在lerna架构下,前两者可直接抽取到一个独立的项目,然后被其他项目引用,比如在我的demo中,可以像其他依赖包一样直接引入shared项目, lerna会自动识别并把它导向内部项目。

import shared from 'shared'

这跟直接封装成npm包的一大区别就是实时更新,修改立刻可见,就像在同一个项目一样,不影响开发和调试。

git钩子和自定义脚本的重用

我尝试把处理git钩子的工具husky安装到了根目录,触发的事件和自定义脚本能覆盖到每个项目,给这部分代码重用带来了极大便利。比如,不少项目会添加自定义脚本来约束git commit提交时的消息描述,在lerna架构下,只需写一次即可。

eslint的重用

那些常常需要在根目录添加配置文件的第三方依赖,比如eslint、prettier、babel等,在lerna中无法简单粗暴的提升合并到一处。因此,对于eslint这种前端开发已不可或缺的工具,可以尝试将所有配置项抽取到独立项目,然后安装第三方依赖的方式引入,类似eslint-config-airbnb,eslint-config-prettier,eslint-config-google这样。

不得不说,即便不用lerna框架我们也可以这么做,只不过在`lerna`框架下修改立刻可见,方便了调试和开发。

lerna框架下的CI/CD

多项目的结构无疑给CI/CD带来挑战,好在主流的CI框架能完美解决这个问题。比如在gitlab上,only/changes参数完全满足了我们的需求,让我们可以为每一个子项目设置单独的pipeline,比如现在我们设置一个pipeline,只当rntest项目下的文件被修改时才会触发:

在lerna框架下,所有项目都合在一个工程里,但CI/CD并不必这样。通过把脚本中的关键参数配置到CI/CD的项目内里,共用同一份.gitlab-ci.yml文件,从而能够实现每个子项目对应一个独立的CI/CD项目,最终CI/CD结构如下图:

lerna框架下的子项目权限

由于所有的项目都归并到了一个lerna工程下,一旦有了访问权限意味着你可以修改所有子项目中的代码,在实际的开发工作中多多少少会带来一些麻烦。比如说,开发web和开发mobile平台的是两个不同的团队,假如我作为web组的一员,一不小心修改了或删除了mobile项目的文件该怎么办?假如不加入任何限制,这种事情迟早会发生,我想这可能是lerna框架与生俱来的的痛点。

不幸的是,在lerna框架下,gitlab或github这类第三方代码托管平台,本身的权限管理功能无法解决这问题。但好在有其他工具的帮助可以缓解这种痛,我尝试用来约束开源贡献者提交PR规范的工具dangerjs来完成权限分隔,利用的信息就是当前gitlab账号的用户名,看起来效果还不错。

可以看到,此工具会在合并MR时,判断出我gitlab账号没有权限修改rntest子项目内的文件,从而禁止合并此MR,并将这些信息自动添加到MR的评论里。当然,脚本判断是自己写的仅用作演示,逻辑比较简陋,脚本代码如下:

关于dangerjs的部分我会另写一篇文章详细介绍。

结语

大前端项目将会是前端发展的趋势,如何更好的管理大前端项目是每一位前端开发躲不开的课题。lerna框架通过合而为一的理念提供了一种解决方案,通过扬长避短,我们可以发挥出lerna的最大效用。假如你还没有用过,也许,下一个项目就可以试试看。

参考资料

  • https://github.com/lerna/lerna
  • https://gitlab.com/twomeetings/lerna-demo (文章中的demo)
  • https://classic.yarnpkg.com/en/docs/workspaces/

git前端工程实现ci_大前端项目代码重用,也许lerna是最好的选择相关推荐

  1. 爱前端2018全栈大前端_启动2018年前端工具调查

    爱前端2018全栈大前端 by Ashley Watson-Nolan 通过阿什利沃森-诺兰 启动2018年前端工具调查 (Launching the Front-End Tooling Survey ...

  2. 【前端之路】前端技术简介,大前端的发展史

    前言 看了很多前端发展史,大多数前端大牛们都将前端的发展分为三个阶段,"网页制作"."前端开发"."后端开发".其实最长看到的还是" ...

  3. 到底大前端是什么 一般大前端技术有哪些

    到底大前端是什么?一般大前端技术有哪些?Web前端是随着移动互联网的发展以及用户体验度的提升而诞生的新职业,入门简单.市场广阔,吸引了很多人入行.然而,近几年,大前端出现在人们面前,有人好奇什么是大前 ...

  4. 前端从入门到大前端学习流程总结

    第一阶段: HTML+CSS: HTML进阶.CSS进阶.div+css布局.HTML+css整站开发. JavaScript基础: Js基础教程.js内置对象常用方法.常见DOM树操作大全.ECMA ...

  5. git clone拉取过大的项目拉不下来的解决方法

    在地址后加上 –depth=1 depth用于指定克隆深度,为1即表示只克隆最近一次commit git clone xxx.git --depth=1

  6. 做一个合格的前端,gulp资源大集合

    承接前一篇<做一个合格的前端,gulp自动化构建工具入门教程>故而整理了如下gulp插件资源大全. **[我的新作观点网:http://www.guandn.com (观点网是一个猎获新奇 ...

  7. 2021 大前端技术回顾及未来展望

    作者:腾讯 IMWeb 前端团队 2021 年大前端领域没有出现革命性的明星项目,但在各个细分的技术领域都有一定的拓展与深耕,有很多新技术或者新特性有望在 2022 年迎来爆发.在互联网 " ...

  8. 前端18个月难度翻番?来这里把握大前端技术本质进展丨稀土开发者大会

    图片来源:pexels.com "别更新了,学不动了"向来是前端开发群体的切肤之痛: React 还没学明白,Vue 就出来了: Vue 2.0 还没上手,3.0 就发布了: No ...

  9. 为前端工程之崛起而编程!

    作者 | 蚂蚁保险体验技术团队 责编 | 胡巍巍 程序员转行学什么语言? https://edu.csdn.net/topic/ai30?utm_source=csdn_bw 本文经授权转载知乎&qu ...

最新文章

  1. 2月书讯 | 冬奥结束看什么?看看“天花板”级别新作!
  2. Lintcode 655解题思路和c++代码
  3. 错误 未找到引用源_你不理解的EXCEL函数中常见的错误值,都在这里
  4. 云原生 DevOps 的 5 步升级路径
  5. NPS cisco 802.1x window7 实现认证接入网络
  6. Javascript 思维导图
  7. mysql主从复制缺陷_mysql主从复制及遇到的坑
  8. mysql 批量远程_【shell--批量远程MySQL,执行命令】-【工作总结】
  9. Noip 2014酱油记+简要题解
  10. linux服务器安装zookeeper本地项目远程连接
  11. Python:学习笔记之变量
  12. 疫情之下, 远程办公软件是如何逆势增长的?
  13. SSCI写作--期刊检索和基本介绍
  14. jenkins中配置git下载代码
  15. 云计算如何从计算机发展而来,云计算是如何发展起来的?
  16. 删除文件出现“文件正在使用或正在打开”
  17. html5写自我介绍,一分钟标签式自我介绍4篇
  18. 输入一个大写字母,显示三角形
  19. 计蒜客——恋爱纪念日(学习如何格式化打印日期)
  20. 怎样申请微信公众平台接口测试帐号

热门文章

  1. 工作102:设置url实现查询 秒呀
  2. 工作58:element三级列表的问题
  3. 前端学习(1345):用户的增删改查操作2
  4. java学习(109):StringBuilder,stringbuffer,string区别
  5. Linux 普通用户和超级用户的切换
  6. oracle锁表怎么解决,Oracle锁表问题的简捷处理技巧
  7. 深度学习算法简要综述(下)
  8. java pdf文件压缩_PDF文件压缩转换教程
  9. python logistic回归_logistic回归介绍与源码分析
  10. 再度吐槽,PHP在centos7的安装方式稍不注意可能就打击你的积极性