什么是开源项目?

在一部分人的眼中, 我想大概就是将源代码开放出来, 放在 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!