最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 实习生在开源项目的求生经历:认识项目

    正文概述 掘金(滴滴前端技术)   2021-04-01   579

    本文将站在一个实习生的角度,分享笔者在 LogicFlow 中的实习经验和对于所遇问题的一些分析解决思路。本篇文章并不是把实习总结一条条的罗列出来,而是把实习的经历和技术文章结合到一起,讲述实习生是如何在开源项目中快速成长的,与技术文章相比,阅读起来相对轻松。

    前言

    往前数算恰好一整年,当时大三的我刚刚加入春招大军,正在一场场面试中因被面试官拒绝而怀疑自我,又在一次次被拒后的自我反思中重拾自信,过了两个多月才在春招的末尾找到了第一份实习工作,随即跨越半个中国来到深圳的一家银行类公司,跟着师兄做了一些零零散散的小项目。在第一份实习中,最主要的收获仅仅是感受到了职场与校园之间的一些差异,而在技术上,由于受到项目体量的限制,成长速度较为缓慢。第一份实习接近尾声时恰逢秋招伊始,或许是受益于第一段实习的经历,我的简历和面试都获得了不错的反馈,最终从手里的 offer 中选择了滴滴,校招也就此顺利收官。

    与滴滴签约后,想着早些熟悉一下以后的同事和项目,我提前来到北京实习。入职第一天,中午吃饭时从师兄口中得知,团队正在做一个开源项目(LogicFlow),我实习阶段的主要工作就是协助他们做一些开发。

    听到开源项目的时候,我的内心一颤,在潜意识里,开源项目开发难度大,且对开发者的技术水平要求高,自觉有些难以胜任,同时又觉得异常幸运,从来没有想到可以在实习阶段赶上“造火箭”,未来会有大量的机遇推动我去学习新的知识,就这样带着一整年中最大的幸运开始了自己的实习生活。

    启动项目

    刚入职时,组内大佬们就已经完成了 LogicFlow 的核心功能以及对应文档,此时的 LogicFlow 还未开源,我的起步工作是为文档添加可操作的示例。

    初次见面

    拿到内部仓库的访问权限后,我把代码下载到本地,粗略浏览了一下项目目录的大致结构:

    LogicFlow
    ├── docs		    // 文档
    ├── examples		    // 示例
    ├── packages
    │   ├── core		    // 核心包
    │   │   ├── src
    │   │   └── package.json
    │   ├── extension	    // 拓展包
    │   │   ├── src
    │   │   └── package.json
    │   └── site		    // 调试示例
    │       ├── src
    │       └── package.json
    ├── .commitlintrc.js
    ├── babel.config.js
    ├── eslintrc.js
    ├── .gitignore
    ├── lerna.json
    ├── package.json
    ├── developer.md
    ├── README.md
    └── yarn.lock
    

    看完目录后我获取到了以下主要信息:

    • LogicFlow 的文档在 docs 目录下
    • 我要开发的文档示例在 examples 目录下
    • packages 目录中包含了 LogicFlow 的核心包、拓展包、示例站点
    • 一个从来没有见过的文件 - lerna.json
    • 开发者上手指引 - developer.md
    • LogicFlow 项目介绍 - README.md

    产生疑惑

    看完目录后确定了下一步要做的事情:跟着 developer.md 为项目安装依赖。

    从 developer.md 中可以得知安装依赖的命令:

    npm run bootstrap
    

    执行完成之后,LogicFlow 的根目录和 examples、core、extension、site 目录下都多了一个 node_modules 文件夹,此时我产生了几个疑问:

    • 为什么 LogicFlow 要在一个项目中存放多个项目?
    • npm run bootstrap 命令是如何做到同时为多个项目安装依赖的?

    好奇心驱使我查看了 npm run bootstrap 中的原始命令,在根目录的 package.json 中,bootstrap 是这样定义的:

    {
      "scripts": {
        "bootstrap": "yarn && lerna bootstrap",
      }
    }
    

    很明显,npm run bootstrap 先通过 yarn 根据根目录的 package.json 为项目安装了全局依赖,然后通过 lerna bootstrap 为 examples、core、extension 和 site 各自安装了依赖。

    分析盲点(monorepo 与 lerna)

    到目前为止,我可以确定 LogicFlow 使用 lerna 这个东西对项目进行了工程化管理,lerna 支持了一个项目中可以存放多个子项目,同时 lerna 对我来说是一个新的知识盲点。

    带着疑惑,找到了 lerna 的代码仓库,在官方 README.md 中,我快速捕捉了以下关键信息:

    • lerna 是一个 JavaScript 项目的管理工具,这些项目内部可以包含多个包
    • 这种一个项目包含多个包的形式被称为 multi-package repository(或者 monorepo)

    同时找到了 lerna 的核心命令 lerna bootstrap,它主要完成了以下内容:

    • 在项目的每个包的目录下执行 npm install,为其安装外部依赖
    • 为相互依赖的两个包之间建立软链(symlink)

    软链关系如下:

    /node_modules
    /examples
        └── node_modules
            ├── @logicflow/core --> /packages/core // 软链
    	└── @logicflow/extension --> /packages/extension // 软链
    /packages
        ├── core
        │   └── node_modules
        ├── extension
        │   └── node_modules
        │       └── @logicflow/core --> /packages/core // 软链
        └── site
            └── node_modules
                ├── @logicflow/core --> /packages/core // 软链
                └── @logicflow/extension -> /packages/extension // 软链
    

    现在就可以解释之前的几个疑问了:

    • npm run bootstrap 命令是如何做到同时为多个项目安装依赖的?
      • npm run bootstrap 在每个包目录下执行了 npm install
    • 为什么 LogicFlow 要在一个项目中存放多个项目?
      • extension 依赖于 core,而 examples 和 site 依赖于 extension + core,将它们放到一个项目中可以实现同时开发、同时发版,且 lerna 的 symlink 可以保证各个包直接依赖于其他包在本地的最新代码
    • 根目录下那个从来没有见过的文件 lerna.json 是干啥的?
      • 是 lerna 的配置文件,可以告诉 lerna 项目中存在哪些 packages

    成功启动

    已经知道,各个包之间可以直接引用本地的最新代码进行开发,现在我们应该在启动项目之前,先把各个包构建一下以便其他包引用,如 developer.md 中的构建命令:

    # 先构建类型
    # LogicFlow 使用 TS 进行开发,不同的包之间存在类型依赖
    npm run build:types
    
    # 构建源码
    npm run build
    

    在根目录执行完上面两个命令之后,就可以进入 examples 目录进行开发调试了:

    cd examples
    npm run start
    

    工具优化

    到了 LogicFlow 开源时,项目的多包管理形式发生了新的变化。在 LogicFlow 正式发布的过程中,师兄添加了一个 yarn workspaces 的功能,这同样又触及到了我的知识盲区。

    新的疑问(workspaces)

    有了 yarn workspaces 之后,package.json 发生了变更:

    {
      "workspaces": ["packages/*", "examples"],
      "scripts": {
        "bootstrap": "yarn",
      }
    } 
    

    在 package.json 中新增了一个 workspaces 的字段,而 npm run bootstrap 命令只通过执行 yarn 来安装依赖。安装依赖之后,与添加 yarn workspace 之前相比,唯一不同的点来自于各个包的 node_modules 内部,即各个包中如果有相同的依赖,那么这些依赖会被提取到根目录下的 node_modules 中,而整个项目在本地的体积就会大大缩小。

    例如,在 core、extension、examples、site 这四个包中都使用了 @babel/core 这个工具,那么 @babel/core 就会被提取到根目录下的 node_modules 中,而那四个包的 node_modules 目录就缩减了下来。

    /node_modules
        ├── @babel/core
        ├── @logicflow/core --> /packages/core // 软链
        └── @logicflow/extension --> /packages/extension // 软链
    /examples
        └── node_modules
    /packages
        ├── core
        │   └── node_modules
        ├── extension
        │   └── node_modules
        └── site
            └── node_modules
    

    与添加 yarn workspaces 之前相比,最重要的一点是软链(symlink)的功能保存了下来,到此为止,这个 yarn workspaces 又让我产生了新的疑惑:

    • 既然 yarn workspaces 和 lerna 都可以为各个包安装依赖并添加软链,那么这两者的区别是什么?
    • 为什么有了 yarn workspaces 之后,仍然要保留 lerna?

    带着这几个疑问,又开始了新的探索。

    workspaces 与 lerna 的对比

    同样的,我找到了 yarn 对 workspaces 的介绍,文档中表示,yarn workspaces 能够完成以下任务:

    • 可以为本地相互依赖的包之间创建软链(symlink)
    • 将各个包之间的依赖安装到一起,放到根目录下
    • 各个包使用同一个 yarn.lock 文件,以减少冲突,方便查看

    也就是说,yarn workspaces 同样也是一个 monorepo 的管理工具,但是它所提供的功能仅仅与 lerna 提供的底层功能一样,为本地相互依赖的包建立软链,并在此基础上进行优化,将各个包的共同依赖抽离出来到根目录。

    yarn workspaces 除了提供 lerna 的底层功能以外,其他高级功能均不支持,这就是为什么有了 yarn workspaces 之后,LogicFlow 仍然保留 lerna 的原因:

    • 使用 yarn workspaces 来代替 lerna bootstrap 安装依赖
    • 仍然使用 lerna 所提供的各种高级功能,例如:
      • 使用 lerna version 为各个包的变更代码添加 tag
      • 使用 lerna publish 来同时发布多个包

    所以,针对于 monorepo 的形式,我们可以同时使用 workspaces 和 lerna 来进行项目管理。另外,在 npm 7.x 版本中也已经支持了 workspaces 功能。

    思考总结

    从刚加入 LogicFlow 时,项目就已经开始使用 monorepo 的管理形式了,那么就会有对应的疑问,LogicFlow 为什么要用 monorepo 呢,它的优点在哪里,它有没有什么缺点呢?

    monorepo 的优点

    以 LogicFlow 为例,我总结了 monorepo 为项目带来的一些优点:

    便于代码引用

    monorepo 可以保证 extension 直接引用到本地 core 的最新代码,如果是 multirepo 的形式,需要先经过 core 的发包,然后在 extension 中下载使用。实习生在开源项目的求生经历:认识项目

    monorepo 可以在开发过程中省去对 core 包的频繁发版与安装。

    便于依赖管理

    monorepo 可以一次为多个包安装依赖,如果是 multirepo,需要为每个项目都安装一次依赖。实习生在开源项目的求生经历:认识项目

    使用前文中的 workspaces,还可以将相同的依赖从各个包中抽离出来,减少整个项目在本地的体积。

    便于快速发版

    在 LogicFlow 中,extension 依赖于 core 的代码,当 core 发生变更后,extension 常常也要随之改变,为了保证这两个包之间的依赖关系清晰稳定,LogicFlow 始终保持两者的版本号一致,这就需要同步地快速发版,monorepo 可以保证同时对多个包进行操作。

    实习生在开源项目的求生经历:认识项目

    monorepo 的缺点

    实际上,monorepo 的优点基本是由各种工具在 monorepo 的基础上带来的,其 monorepo 本身也存在缺点。

    管理成本

    在 monorepo 中进行多个包的开发、联调、上线时,仍然需要执行多次打包或上线的命令,例如,当 LogicFlow 的 core 和 extension 发生变动后,对应的 examples 也会变化,这就需要先分别对 core 和 extension 进行打包,然后供 examples 的开发使用,所以 monorepo 的每一个动作包含了多个项目的步骤,使得管理成本上升。

    解决方案:引入 lerna 来管理 monorepo,可以实现对多个包的同时构建或上线等。

    项目体积变大

    当所有的包都放到一个项目里,安装依赖之后整个项目的体积会变大,多个相似的 node_modules 会使得项目体积飙升。

    解决方案:使用 workspaces 将不同包中相同的依赖安装到根目录下,以便依赖的复用。

    commits 易混乱

    在一个 git repository 中修改多个包的代码,会导致多个包的 commits 掺杂在一起,在查看 commit log 的过程中会增加分析成本。

    解决方案:规范 commit 格式,在 commit 中注明改动所属的包,例如:fix(core): something。

    访问权限控制缺失

    多个包放到同一个仓库中意味着它们的访问权限必须是一致的,对于 LogicFlow 这种开源项目并没有影响,但当某些项目拥有不同访问权限的包时,monorepo 并不适用。

    梦的开始

    每个程序员都会懂得,职业生涯中能够有一个好的项目作为磨练自己的机会是非常难得的,开源项目脱离了业务需求中逻辑的重复性和复杂性,保留了对行业内各种前沿技术的应用,是让开发者快速成长的好机会。能够有机会加入 LogicFlow,对我这个实习生而言是非常幸运的,如同做梦一样,在 LogicFlow 中所遇到的每一个疑问和难题,都像是有位老师在指引我前行。

    最后

    本篇文章以一个实习生的视角,讲述了在第一次面对开源项目 LogicFlow 时所遇到的“新概念” - monorepo,并分享了笔者对于 monorepo 学习和理解,monorepo 本身瑕不掩瑜,是开源项目可以考虑使用的一种包的管理形式,在后面的实习阶段,笔者还会将其他所遇到的有意思的新挑战分享给大家。

    更多阅读资料:

    • LogicFlow github:github.com/didi/LogicF…
    • 官方文档:logic-flow.org/LogicFlow
    • 设计原理总述:juejin.cn/post/693341…
    • LogicFlow 拓展机制:juejin.cn/post/693831…
    • 边的绘制与交互:juejin.cn/post/694272…
    • 添加微信号进用户群:logic-flow

    起源地下载网 » 实习生在开源项目的求生经历:认识项目

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元