什么是开源项目?

在一部分人的眼中,我想大概就是将源代码开放出来,放在 Github 之类的平台中

1
2
// index.ts
export const myModule = () => {};
1
2
3
4
{
"version": "0.0.1",
"name: "test"
}
1
2
npm login
npm publish

光速发布,然后就没有然后了,一次性开源。

在另一部分人的眼中,这是开源项目

2021-03-12-17-51-54-2021312175156

从我自己的角度来说,开源不是 KPI, 不是晋升的方式,是单纯的兴趣爱好,一种自我奉献,不管是几行代码的开源

2021-03-11-22-27-58-2021311222759

还是 Linux 这种复杂,伟大的开源项目,背后都是作者和所有参与者的辛苦付出,我理解的开源项目,代码开源,只是整个过程中的第一步,我以我自己维护的 react-music-player 为例,讲述我是如何开发并学习到相关知识点的

我的第一个插件

作为前端,背靠 npm 这一个庞大的生态,站在巨人的肩膀上进行开发,非常的便捷高效,而相关模块,你都可以在 Github 上找到相关的代码,我编写的第一个开源模块,是一个 Jquery 实现的 上传插件,如果你也开发过,这一句代码你肯定很熟悉,这是啥,这是梦开始的地方!

1
(function (win, $) {})(window, jQuery);

当然,这种模式很快被淘汰了,现在都是组件化,起因是我自己用 React + Node.js 实现了一个博客,想继承一个播放器,在 Github 上找了一圈都没有合适的,所以只有自己实现一个,单纯从技术实现来说,实现一个前端的音频播放器很简单,毕竟不用自己编解码,基于 <audio/> 标签相关的 API 开发即可,之后的事,才是打开了新世界的大门

要啥文档,你不知道自己看代码吗?

没错,代码写完了,你把它发布到了 npm, 也在 Github 创了 repo, 但是这个是开源出去给人家用的,第一件事就是文档,没错,一个 README 差点要了我的老命

2021-03-11-22-42-31-2021311224232

代码是你自己写的,但是站在其他人的视角,需要让被人有一个清晰的认识,所以要有

  • 如何安装
  • 如何使用
  • 一图胜前言的预览截图
  • 一些关键信息的 badge
  • 要不要加一些 emoji 让文档看起来好看点
  • 这个东西是干啥用的
  • 详细的 API 文档
  • 如何定制化
  • 如何贡献代码
  • 许可证是啥

如果你自己也写过,你会明白写清楚这些不是一时半会能完成的

这些网站,可以生成一些 badge, 展示在 README 上

当然,也有大神提供了 README 生成器:readme-md-generator, 可以用它来生成一份精美的文档

这个网站可以选择一些精美的 emoji, 用 来装饰你的 README

然后再添加一张贡献者图片:这个网站可以生成

2021-03-11-23-52-16-2021311235217

弄完了这些,还需要一个可以在线访问的链接,用 gh pages 即可

2021-03-11-23-03-08-20213112338

对于我这个播放器,我是自己写了一些 demo 页的代码,对于常规的项目来说,可以选择开源的文档生成器,比如

2021-03-11-23-07-41-202131123742

选择一个你自己喜欢的文档工具,然后部署在 gh pages 上,这样你就有了一个像那么回事的官网,当然 gh pages 是国外镜像,速度可能偏慢,你也可以选择部署在 类似于 gitee 之类的国内镜像上

现代的工程化

翻看一些知名开源项目,你会发现工程化相关的配置文件很多,我的一个小小的播放器,配置文件就有这么多

2021-03-11-22-48-36-2021311224837

  • 必备的格式化:prettier
  • 静态检查:eslint
  • 单元测试:jest
  • 代码提交格式:commitlint
  • css 预编译:postcss
  • 自动发布:semantic-release
  • 打包编译:webpack, babel
  • 提交检查:lint-staged, husky
  • css 检查:stylelint
  • 单元测试覆盖率:codecov
  • 变更说明:ChangeLog

作为前端,这一套应该都非常了解了,所有一套配置下来,然后再编写 npm scripts, 写一些常用的工作流,比如 本地开发,部署打包 等等,作为开源组件,通常还会提供 UMD, Commonjs, ES Module 等模块,供用户选择,打包工具也是多种多样,比如 ts 就直接用 tsc, 也可以用 babel, rollup 等等。.. 有时候你会感叹前端生态百花齐放是不是一件坏事 :)

2021-03-11-23-11-25-2021311231126

第一个 Issue

叮~, 有一天,你在路上,邮件通知你,你的开源项目收到了一个 Issue, 第一个 Issue, 意味着你的项目有人关注,有人使用了,你急冲冲的打开电脑查看,发现问题没有说明具体原因,什么版本,报错是啥,总之就是什么有用的信息都没有,接下来就是漫长的沟通交流,这时候,Issue Template 就该登场了,在根目录新建 .github/ISSUE_TEMPLATE 就可以预设模板,比如我的就是

2021-03-11-23-20-50-2021311232051

通过模板,可以减少很多无意义的沟通,提高效率,不然真的很心累,但是事情不是这么简单,因为世界上有这样一群人:”你尽管设置模板,我按照你的要求填算我输”, 是的,随便翻几个知名开源项目的 Issue, 你都会发现这样的现象,比如 Ant Design 随便找一个,贴一段代码,还不是 md 格式的,除此之外没有任何信息,真的非常蛋疼

2021-03-11-23-24-24-2021311232425

对于我这种播放器项目还好,可能一个月最多一两个 Issue, 无所谓,对于其他大型项目来说,这种对维护者来说是很累的,所以通常都用机器人的方式自动关闭这种 Issue. “你尽管提,回答你算我输”~

第一个 PR

叮~, 有一天,你在路上,邮件又通知你了,你的开源项目收到了一个 PR: “我艹,牛逼啊”, 打开电脑一看,好家伙,原来是机器人,帮我更新依赖,白高兴一场

2021-03-11-23-29-04-202131123295

不过也有靠谱的哥们,直接来了几个 PR, 还有一个设计师,直接 免费帮我设计 LOGO, 很快啊,我就把它放在了 README 上,白嫖美滋滋。后面,偶尔还是会收到一些 PR, 可能小到一个错别字,或者一个 ts 定义写错了,他们的这些暖心的举动,第一次让我感受到了开源的魅力,就是那种大家一起贡献,没有利益关系的感觉,很爽,很有成就感

Issue label

2021-03-12-17-07-29-202131217731

当 Issue 逐渐多了起来,可以通过 Label 将它分组,它是否是一个 bug? 还是一个重复的问题,或者是一个没有任何有价值的意义问题,这样就可以更好的进行管理,通过定制一些机器人进行自动回复,自动关闭。

Github Action 和 App

在平时的 Issue, 和 PR 管理中,我们还可以借助 一些 Github Action 和 App 来帮助我们自动化完成一些事,比如跑 lint,test, 打包大小检测,自动添加 tag 之类的

2021-03-11-23-39-04-202131123395 2021-03-11-23-38-35-2021311233836

比较推荐的是:

  • Codecov: 在每一次的 PR 中输出当前测试覆盖率
  • Issue-Label Bot: 自动根据你的 Issue 类型进行打标签
  • codesandbox: 对当前 PR 自动创建一个 code sandbox
  • Netlify: 提供当前 PR 的一些在线链接 便于预览,但是超出免费使用量要收费,比如我这种小项目可以用,大项目 PR 比较频繁就算了,推荐 surge
  • surge-preview: 偏右大神基于 surge 封装的一个 action, 用了都说好
  • issues-helper: 一个工具 action 集合,很实用,比如自动关闭 issue, 添加评论等等

使用 issues-helper 定制一些 Action CI, 在我们对 Issue 或者 PR 打上标签时,可以自动评论,减少一些重复的工作量,体验非常好

2021-03-11-23-49-30-2021311234930

2021-03-11-23-43-34-2021311234335

当好心人发起一个 PR 的时候,可以使用 Netlify 或者 surge-preview, 自动生成预览链接,可以很便捷的查看

2021-03-12-17-12-54-2021312171255

关心他人的代码质量,在人工 review 之前可以通过 CI 进行一些简单的 Lint 检查,比如提交前后的代码覆盖率变化,尺寸变化等等

2021-03-12-17-14-35-2021312171437

更多的好东西,可以在 https://github.com/marketplace 中自行发现

自动发布

当开源项目发布后,通常需要对应的 更新日志说明,这样使用者才知道你改了什么,当然这也是有很多开源工具帮你做这些事情,当然前提是你的提交记录严格按照例如 Angular 提交规范,feat, fix 之类的规则:

2021-03-12-17-21-48-2021312172149

  • 命令行工具帮你填写提交信息,还可以添加 emoji : gitmoji-cli

2021-03-12-17-23-43-2021312172345

当然这一切还可以更智能一点,通过强大的 Github Action, 通过 CI 配合这些开源工具,实现自动发布,我的发布过程如下 (参考 Taro):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
name: 📦 Auto Release

on:
push:
branches:
- master

env:
CI: true

jobs:
release:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]')"
strategy:
matrix:
node-version: [12.x]

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}

- name: Install dependencies
run: yarn

- name: Build, and test
run: |
yarn lint
yarn build
yarn test
env:
CI: true

- name: Release
if: startsWith( env.commitmsg , 'chore(release):' )
run: yarn release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

可以发起一个 PR, 或者直接基于 master, 如果 commit 信息以 chore(release) 开头,就会自动打包,跑测试,然后使用 semantic-release 发布

1
2
3
4
5
6
7
// package.json

{
"scripts": {
"release": "semantic-release"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
branch: 'master',
plugins: [
'@semantic-release/commit-analyzer',
'@semantic-release/release-notes-generator',
'@semantic-release/changelog',
[
'@semantic-release/git',
{
message: 'chore(release): 🤖 ${nextRelease.version} [ci skip]',
},
],
'@semantic-release/npm',
'@semantic-release/github',
],
preset: 'angular',
};

效果如下:

2021-03-12-17-31-52-2021312173153

自动添加 tag

2021-03-12-17-32-13-2021312173214

自动生成 changelog

2021-03-12-17-32-49-2021312173250

如果有部分提交是通过 PR 的方式,那么还会自动评论并关闭,一个字:真 TM 爽

2021-03-12-17-33-50-2021312173351

另外有一个小点,semantic-release 会根据当前 commit 自动判断最新的版本号,会触发一次提交

1
2
3
4
5
6
7
8
{
[
'@semantic-release/git',
{
message: 'chore(release): 🤖 ${nextRelease.version} [ci skip]',
},
],
}
1
2
3
4
jobs:
release:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]')"

这种 commit 可以不用走 CI, 所以可以配合 Action 自动跳过。

功能的增加和改进

我发现开源还有一个好处就是,使用者会提供一些很有建设意义的问题,或者是 bug, 帮助你不断的完善,在这之前,我是万万没想到,一个简单的音乐播放器,会有这么多的问题,每个人的使用场景不一样,所以看问题的角度也不一样,不断的交流,不断的改进,还会让我学到很多新知识,比如非常酷炫的 media-session, 整个 audio api 的深度使用,响应式,动画的各种适配,移动端音频的各种 bug 及优化,虽然无偿的牺牲了自己的业务时间,但是也是有回报的,可能不是传统意义上金钱的回报,虽然我技术也达不到,不能像尤大这种通过开源走向人生巅峰,但是那种成就满足感,是非常巴适的!

另外一点就是我比较喜欢逛 Github, 经常会看到很多大爷似的白嫖党,完全理所当然化,给人的感觉就是 “爷用你的东西是看的起你,赶紧给我修,赶紧给我改,我要加这个,我要加那个”, 提个问题也说不到重点,挤牙膏,人菜还不自知,也不去了解,简直让人头皮发麻

2021-03-11-23-56-05-202131123566

生活的平衡

写这篇文章的时候,看了一下 Issue, 还有两个未处理,147 个已经关闭或处理的,这还仅仅是一个不起眼小小的播放器,能想象一下大型的项目吗?比如 Flutter [手动滑稽]

2021-03-12-17-42-13-2021312174215

播放器基本上是三年前写的,没想到直到今天,我都还在维护它

2021-03-12-17-44-09-2021312174410

但过程是怎样的呢?现实可能是忙碌的工作一天结束后,回到家,打开电脑,处理播放器的 bug, 功能开发,一把唆之后,看了看时间,我艹,可能就是 12 点了!不太好形容那种感觉,说实话我也说不清是什么驱使我坚持做这些事情,也许这就是传说中的热爱?每天脑子里还会经常浮现这些问题,有一种解决掉的冲动,有时候也想放弃,心想,妈的,全是白嫖怪,也不帮我贡献,还给老子提需求,自己不知道加吗?总是如此反复,有时候又想其他大佬不也是如此吗?我和他们比又算啥?心里这样想又会平衡一点!

最后

上面说到的,也只是我了解学习到的一小部分,另外还有 Github Sponsor 之类的赞助体系,我就没有研究过,总而言之,我作为一个卑微的底层前端开发,真真切切的享受到了开源社区带来的好处,也就是所谓的站在巨人的肩膀上,虽然自己技术有限,但也在尝试做自己力所能及的事情,并享受这个过程,也希望自己能一直坚持下来,向大佬们学习,respect!