個人/團隊/公司開源,Joyqi 談貢獻開源的「不同姿勢」

AnswerDev發表於2022-12-15

前不久,Answer.dev 創始人 @Joyqi 受到邀請,在剛剛結束的 GitHub Universe 的 Local Party 上做了題為「用 GitHub 構建開源專案的各種姿勢」的主題分享。以下為他的分享實錄。

Hello 大家好,我是 Joyqi。

剛有同學提問,很多學生在大學期間怎樣參與開源專案,怎樣做自己的第一個開源專案。我的開源生涯也是從大學時間開始,稍後我會分享一下我的開源歷程。其實開源可以有不同的姿勢,不一定是你去一家公司裡面參與開源專案,也可以透過其他方式開始。

先從技術的角度自我介紹一下,我自 2006 年開始參與開源,因為我 2007 年畢業,所以其實大學時就已開始做開源專案。那時全世界的開源運動還處於興起的階段,中國的開源專案也應該是第一批,所以當時我算是挺有幸能參與到開源的世界。

image.png

下面是當時的一些開源平臺,有些如果你在網際網路待的時間比較長的話,會知道這些平臺。在 GitHub 之前就有這種開源平臺,最早叫 SourceFroge,如果知道那你們夠 「老」 的。後面是 Google Code,不過很遺憾,他們做了一段時間且在 GitHub 起來後就不做了。這兩個前面應該都是用 SVN,即在 Git 之前的版本管理工具都用 SVN 來做的。我自己本身的技術棧、服務端、前端移動端其實都做過,所謂全棧工程師,其實就是全乾,因為之前從事的工作崗位要求我做這些工作,所以我對技術上是很開放的。我自己的開源專案也是各種端都有,我覺得開源是一件挺好玩的事情。

個人開源:用得好所以開源了

說到參與開源的各種姿勢,先從最普通的姿勢,即大家很多同學或朋友最能接受的一個開源姿勢 —— 用得好所以開源了。

這是我的一個小的個人專案,用著比較開心,那它是一個什麼專案呢?——給你的身份證圖片打碼。

image.png

我們現在經常要在一些平臺做驗證,需要上傳證件照,但又不放心,就會在上面打碼,比如會打上「僅供用於某些身份驗證」這種透明的碼。當然如果我們用一些網站的 online 專案,其實也會不放心,因為要把我們的圖片傳上去,相當於把身份證也傳上去了,其實更不放心。所以說我就做了一個這樣的專案。

這很簡單,前端的同學應該知道,我當時在學 CoffeeScript,半天時間就搞定了。程式碼其實也只有一兩百行,它沒有任何網路請求,全部用 canvas 去做圖片,然後在圖片上寫上一行字,可以調整間距及顏色,還有透明度。

當初這個簡單的功能並沒有做宣傳,只在群裡面發了一下,後面就不斷有人去 star 去 fork, 這個專案的 fork 數和 star 數的比例還挺高,別看 star 僅不到 300 個,但 fork 卻相當多,有很多人拿這個簡單的專案去實現自己的打碼平臺,我覺得還挺好玩的。

之所以提這個專案,就是因為做開源的初心。我做開源的初心是先解決自己個人的真實痛點,這個痛點是存在的,是我自己想去解決的,且這個痛點對其他人也特別適用。因為我覺得在網際網路上普遍存在隱私洩露的風險,而大家都有這種擔心,所以我把它做出來後,儘管週期很短,但依舊會有這麼多人關注,有這麼多人用,還有很多人提意見,包括有人還給我提 PR 等,這是個好現象。所以,我覺得這種專案對於很多人來說其實難度不大,你們可以去嘗試去做一下這種專案。

另一個專案也挺有意思,我把它取名叫「閃光時刻」。

image.png

很多程式學員都會有突發奇想,即突然覺得我有個想法特別牛,其他人都沒實現過,我想把它給做出來。然後當時我就寫了一個這樣的專案——Mobile Device JS ,我們知道 WebGL 有個介面,它可以讀取我們顯示卡的資訊,比如像 iPhone ,它就可以透過其介面讀取你手機的顯示卡/處理器 A1 還是 A12 或是 A13 的資訊。將處理器資訊讀取後,根據解析度就可以很精確地判斷你的機器屬於哪一代 iPhone,可精確的判斷到底是屬於哪個型號的 iPhone,這對很多特殊行業有很大幫助。比如網遊等行業,這是我後來瞭解到的,但是當時我只是覺得這個東西很有趣,我突然發現了這樣的用法,就把它做出來了。

image.png

對此,我還寫了一篇文章發在了 SegmentFault 上,文章的題目叫 「思路清奇:XXXX」,當時挺多人給我評論,挺有趣的。後來有個開發者加我微信,啥話不說先發紅包,我從來沒見過這種情況。有的同學會給自己的開源專案設立贊助通道,大家會去贊助平臺去贊助,但我從沒見過有人上來直接給紅包的。我當時跟他聊了一下,他說他們是一個比較特殊的行業,這個產品給他們解決了一個很大的問題 —— 原來他們一直想很精確的判斷使用者的手機到底是什麼型號,不能只判斷 iPhone 和安卓,必須得判斷是哪一代機型,所以說他覺得我的產品對他特別有幫助,我覺得特別有成就感。當然,我的產品給他帶來的價值其實肯定不止這些錢,但我依舊覺得挺高興的。我覺得這是一個特別特殊的經歷,可以給大家分享一下,所以說開源其實還是可以創造價值的。

image.png

開源還有一種姿勢,有很多的朋友自己從編碼習慣出發做開源,這其實是一種「偷懶」。我自己就做了一個這樣專案,這個專案剛做還沒有什麼 star 和 contributor,它就是一個 GitHub 的模板,比如說你有段時間經常想做一類專案,可以把它做成一個模板。然後你可以做一類專案的時候,用這個模板釋出專案就可以省很多事。最近我寫了很多這種 TS 的專案,就是用 TS 發到 npm 上去,但發現很多動作都是重複的。因此,我看到 GitHub 有這樣的模板功能,便在模板裡面寫了一個 GitHub Action 後,它可以根據你的初始化條目,等初始化專案以後,就可以得到一個標準的 TS 的一個腳手架的專案,在裡面直接寫程式碼就可以,很多東西都不用去配,tsconfig 可以不用去配置。以上就是我從個人角度出發的專案。

其實,該類專案不僅僅是上面所說的模板專案,其實還有很多,比如很多人之前會將 vim 的配置作為一個開源專案。如果大家用 vim 的話,應該會關注這種專案或者 VS Code 的配置或者是諸如此類的這種專案還有指令碼,我們可以提升平時開發效率的一些專案,也可以做開源專案,這是我個人的一些開發專案及怎樣去參與這些開源專案的經驗。

很多專案會有一些 star,有的沒有 star 或是剛釋出出來也沒有關注。但我認為追求 star 並不重要,首先是開源的態度,能把東西做出來,把文件寫好,對其他人有幫助,我覺得能做到這個態度是特別重要的

社群開源:玩大一點

後面可以玩一點高階的開源姿勢,我可以把它叫社群開源。

這是「中國開原始碼力榜」,一個網站,這是我們和開源社以及 OpenDigger 合作的專案。OpenDigger 負責把 GitHub 上最優秀、協作影響力最大的 100 位中國程式設計師找出來,然後我們再把程式設計師的 profile 放到 GitHub 上,去做成一個 Repo,然後這些程式設計師可以來 fork 該 Repo,更新 profile。我們整個專案就完全託管在 GitHub 上,這是完全社群的專案。所以如果你在這個榜單中,就可以 fork 這個專案,然後去提 PR 跟進你的 profile, 然後我們後面寫了一堆 Actions 會自動 build 這個網站,會更新你的 profile。

image.png

大家可以看到,該專案的 PR 其實就是很多人在去更新自己的 profile,然後去增加自己的專案經驗。右邊我們的 Actions 會去做構建然後釋出。我們這個專案是全自動執行的。因為當時我們目標是不想把專案做成一個動態的網站,後面有資料庫,我覺得那個太不酷了,太老了,我們把它做成一個完全公開的,所有的資料、所有的構建過程都以社群化的方式執行。所以,我們就選擇了這樣的方式來做這個專案。

image.png

然後,就是我人生中比較重要的一個專案——我在 2007 年的時候開始做了這個專案,叫 Typecho這個專案現在有 9000 多 star ,從 2007 年做到現在,想想已經有 15 年了,很不可思議,生命力已經出乎了我的意料。創業以後,我工作比較忙,更新的頻次很低,在我們 Typecho 的使用者群裡面,流行一個梗,就是「Typecho 什麼時候更新」。這個梗,在我去參加使用者聚會的時候,大家經常就會拿出來問。因為更新實在太慢,人家都是以月以周為節點更新,我們則是以年為節點來計算更新時間,但我們其實只是大版本沒有更新, commit 還是在經常更新的。

image.png

Typecho 專案其實特別純粹,特別理想化。大學時我就想做一箇中國的 WordPress, 因為 WordPress 當時也在 0.1,我跟他當時基本上是同時間釋出的這個版本。然後我就想做一箇中國的部落格軟體出來,也是 PHP 的,因為當時在大學裡面接觸的第一門動態指令碼語言就是 PHP。我們在做的過程中,遇到了當時在中國開的第一個 WordCamp, 一個面向 WordPress 開發者和愛好者的聚會,因此我就認識了我的很多團隊成員,他們對 Typecho 這個專案很有興趣,想來參與這個專案。所以我們 2007 年的時候就以完全遠端的方式組建了一個這個社群化的開源團隊。

大家都來自天南海北,我們都當時就用郵件列表去做溝通,專案管理也是用 GitHub 的 issue 來做。這麼多年下來,該專案之所以還有如此強的生命力,這也跟我們當初選擇社群化運作分不開。儘管有的人可能比較忙,沒時間更新,但 Typecho 依舊社群運作的專案,大家也可以去提交 PR,可以去提交 issue,也可以去參與到專案中,所以我覺得這個專案可以持續到現在是有原因的。

在該專案的成長過程中,遇到了很多有意思的事,我不知道大家知不知道 PHP 這個語言,其實它分很多版本,每個版本又可以部署在不同的平臺上,然後部署的平臺上又可以有很多不同的部署方式。所以後面我們每天有一個 nightly 版本,每晚會編譯該版本。但編譯環境特別複雜,即多版本多操作、多環境、多 CPU 架構交叉定義。

image.png

GitHub 有一個好處,就是 GitHub Actions Runner 對開源專案是完全免費的。所以儘管編譯特別耗時(每天晚上編譯一次大概需要三個半小時),如果讓我們自己機器去編譯的話,這個是很費錢的。但用 GitHub Runner 來做的話,我覺得還是薅到了很多「羊毛」。最早的時候是所有平臺全部並行全部併發的去編譯,編譯的時候直接把 runner 給搞掛了(不知道是我搞掛了還是它自己本身有問題),所以我們後來換了一下,每個平臺會有一個 stage, 編譯完以後進入到下一個平臺,也相當於做了一個小小的分發,這是我們這個專案比較特殊的一點。

還有一點,就是我們的專案用到了比較多的 GitHub 交叉。GitHub Actions 有 API,我們會在 GitHub 多個專案之間,因為整個 Typecho 專案下面會有多個 Repo,比如說有 Typecho 這個 Repo 它是用來放專案主要程式碼的,Languages 這個 Repo 是用來放所有的多語言的,大家可以看到現大概 17 種語言的都是使用者去提交,然後這兩個 Repo 之間其實是有聯動關係的,做了一個相互交叉的 Trigger。

image.png

如果 Typecho 這邊修改了某一些語句的話,它會 Trigger 到 Typecho Languages 專案,Languages 專案編譯自動把 Typecho 專案的程式碼 clone 下來,然後去編譯 message.bot 這檔案,釋出語言包,之後 Typecho 再從該專案裡下載語言包編譯成一個多語言版本的 Typecho,這實際上是多方觸發的關係,我們把它用 GitHub Actions 做了個實現,這樣就可以減少很多手動過程,由於我們本身人就少,人工特別金貴,因此儘量都自動化。

以上就是 Typecho 的情況。

公司開源:技術能力溢位

由於我們自己在 SegmentFault 也開源了很多自己用到的元件,所以如果公司要做開源專案,或公司的某個產品要去開源,我覺得這是很多國內大廠經常用到的一種開源模式,更多的是來自公司的能力的溢位。

如果你做了一個專案,但由於該專案只能在公司內部用,所以會覺得自己的能力被埋沒了,或是自己的影響力應該可以覆蓋到更遠的地方,所以此時你就該將它開源出來。公司開源的專案有幾個特點

  • 把專案開源出來肯定是來自公司專案的能力溢位 —— 因為你的公司能力,你能達到這個地步,你才會去開源這個專案,所以可能只有優秀的公司才有能力去做開源或做成功的開源。
  • 它是以公司的技術團隊為主體的,就像我們這些專案可能現在還沒有做社群化,只是一起提 issue 或修小的 bug 提一下 PR,但主要還是以我們公司的團隊為主,因為是我們主動將其開源出來的。
  • 另外就是這裡面重復造輪子的事情會比較多,下面兩個例子就是有點吐槽的意味:比如現在看不少大廠的開源專案有很多重複的輪子,早前前端行業裡被吐槽比較多,mix 還有前端很多渲染的專案,都會重複造很多輪子。
  • 為什麼?我覺得可能就是因為在大廠內部有很多能力需要去釋放,可能受到 KPI 影響,所以會重複造輪子,給後面長遠發展造成了影響,有「人走茶涼」的風險。如果團隊有調整的話,該專案就會因為沒有人維護而被「擱淺」。這也是為什麼我們之前用開源,如果沒有基金會維護,只是一個廠商去開源的專案,我們會有這樣的疑慮 —— 他會否有可能過段時間就不維護了?

image.png

我們在做功能的時候,就遇到了剛與 GitLab 的同學一直在聊的這個問題 —— 社群與內部同步。因為這個專案是從公司內部開源出來的,所以它肯定是在公司內部的程式碼託管平臺先做了開發,然後再放到 GitHub 上去。它的開發主體可能還是在內部,只是它會定期地去 push 到外面的 GitHub 的 Repo 上去。因此,這就會存在同步問題。

該問題我們目前已經有了一些解決方法,但也不能說完全解決了 —— 因為存在一些程式碼的同步問題。

  • 目前,我們在程式碼同步方面採用映象的方式,就是 GitLab Mirror 到 GitHub 上去。但這有一個問題,如果你在 GitHub 上有 PR 的話,merge 就會有很大的問題。
  • 所以我們現在也不用 Mirror 的方式了,而是兩邊分開,會有機器人去做同步,如果那邊 GitHub 有 merge 的話,它就會同步到 GitLab 裡面, PR 管理也是這樣,它有一個 webhook,如果那邊有 PR 的話,我們就不會接收這個同步的訊號,而是將其同步到內部的程式碼裡面。
  • 分支裡我們用了一些比較常用的 Flow ,之前用的是 Git Flow ,現在則不常用 。
  • 在這裡,為什麼要強調說一下 CI/CD 呢?就像之前所說,如果將其放 GitHub 上,它的 runner 的計算能力是有限制的,除非買付費 plan,不然其 build 能力是受限的。所以,現在將 build 部分放在我們自己的內部平臺裡面打包編譯,然後社群只做測試,跑單元測試程式碼或是去做比較輕量的一些計算。

以上就是我們內部和外部的程式碼管理平臺的一些經驗。

做了這麼多個人開源專案、公司的開源專案以及社群的開源專案之後,我們就開始思考一個事情,我們能不能將開源這件事情做成一家公司,將公司做成一個開源公司,把我們自己的能力充分展現,把我們主要產品的能力開源出來。

image.png

有了以上積累,我們做了開源問答社群軟體 Answer,該專案正式釋出於 10.24釋出後的第一個星期,就在 GitHub Tending 霸榜了一週左右,不到一個月時間已有 4000 多 star。正因為 SegmentFault 是做問答社群起家的,所以我們積累了大部分問答社群的經驗。在我們做社群的過程中,有很多 B 端的使用者提到他們也需要這樣的社群,能不能幫他們搭這樣的社群,或是怎樣去實現這樣的社群。之前我們很難去響應這種需求,只能提議他來我們社群建一個專區或子站,但我覺得這樣的話他們的需求不能完全滿足,因為他們有些內容是需要完全自定義的或自己去控制自己的資料。

基於這樣的想法,也基於我們在社群開源這麼多年的思考,我們在想能不能把我們在問答社群領域的能力完全開放出來,變成一個開源的專案讓大家來用。這樣其實是顛覆了我們整個商業模式 —— 之前我們就是一個社群公司,透過廣告服務來賺錢。如今,我們變成了一家開源商業公司,一家軟體公司,我們的驅動力也變成了用社群驅動來開發,跟我們此前的驅動方式完全不一樣。

但我覺得開源對商業公司來說是至關重要的,正如剛才有人問韓駿老師是否有想法將開源專案做商業化的時候,我們也在想這個問題 —— 開源帶給商業化最大的一個作用是什麼?其實對商業使用者來說,建立信任是很重要的步驟,為什麼讓使用者相信你去買你的產品?你可以想象一下,為什麼我們要付費買 GitLab ?如果你的公司足夠大,可以支援買 GitLab 這樣產品的話,你為什麼心甘情願掏錢買?或者你買 JetBrians 這種編輯器的理由是什麼?為什麼?因為你用過它的開源產品,你知道它的程式碼,你知道它整個運作流程,你相信它有一個堅持的社群在支撐著這一切的運作,它有著很健壯的力量。對我們軟體開發者而言,健壯性是很必要的一個條件。如果你只是一個小作坊或小公司的話,我很難把自己內部的能力展現給你。但如果開源的話,我可以把我對社群的管理能力統統展現給你。我覺得這對商業化來說是很重要的一步,使用者可以透過這個過程來相信你的產品,相信你的產品可以給他們帶來價值,也相信你可以很好地去發展這個產品。因為他不可能就用一次,肯定要長期去用的。所以,這也是當時我們要做開源公司的最初的思考。

具體到開源公司後面怎麼去做商業化、商業模式,我們想得比較多的就是軟體 SaaS 方面了,後面我們可能會圍繞這樣的能力來去構建商業化產品。以開源模式做公司的話我們會有會遇到一些轉變,首先就是國際化

image.png

由於我們的專案是完全國際化的專案,其文件全是英文,釋出渠道也是在國際渠道,所以它給我們帶來了很多思維上的轉變。之前我們沒有過多地思考這些問題的,但我可以分享出來,大家可以借鑑一下,我們現在也還在處理這些問題當中,比如我們的文件、註釋都是全英文。這一點之前我們可能有些人沒有寫註釋的習慣,或是寫文件的習慣,對他來說是一件很難的事情。但如果你要做一個社群,這兩樣都是特別重要,特別是對一個國際化產品而言,全英文的文件,是使用者瞭解你的第一步。

我們也把英語作為社群的官方語言,現在也有很多中文使用者來提問,我們不會拒絕,但我們會引導大家儘量用英文去提問。

現在,我們在做的一步是將語言檔剝離,然後交給社群去維護。我們現在把它交給到第三方的開源平臺,大家可以在上面幫我們翻譯一些詞條,目前已經有一些翻譯了。

接下來,就是社群化的過程。

image.png

其實剛剛也提到過,我們現在的產品路線圖已是完全社群化了,現在用 GitHub 的 Project 來做路徑圖,用 GitHub 的 Project 來發布這些功能,或是參與討論這些功能,或是它已經實現的功能我們都放在上面。然後告訴大家我們會在哪一個階段完成,比如 Q1、Q2、Q3、Q4,或者還要標註它是哪個版本,比如在 0.3、0.4 哪個版本釋出。在這個過程中,這些功能你都可以參與討論。如果你還有其他的功能建議,也可以在 issue 裡面提出來。提出來後,我們覺得合適的話會把它列入到我們的 Roadmap 裡,這些過程全部是公開的,大家可以在裡面自由討論自己想要的功能。

還有一個就是我們的社群,現在除了傳統社群如 GitHub 社群及 Stack Overflow 等其他類似的社群以外,我們還在一些比較新的國外社群做推廣及社群建設,在上面也可以討論我們的產品,我們在 Reddit 上有頻道,在 Product Hunt 上也釋出了,當時也收穫了特別好的反響和回饋,我們還建立了 Discord 聊天頻道,大家可以在裡面聊我們的產品,和我們官方溝通。

image.png

最後,聊一下在 Answer 專案裡遇到的一些挑戰:

第一,就是文件。剛才也說了,文件對我們很重要,因為之前沒有受過這種專業的文件訓練,所以我覺得這個課我們必須補上。現在我們實際上是在集體學習怎樣編寫一份好的文件,包括文件結構,描述性的語言,包括它的排版。目前都在瘋狂的學習當中,現在還沒有做到足夠好,但我們的態度是一定要編寫一份能讓大家、能讓開發者或使用者閱讀起來很舒心的一份文件。

第二,就是社群答覆時間和工作時間的分配。這是專案釋出以後我們遇到的一個比較大的問題,使用者的問題會集中一段時間在上面提出來,我們要解決的話得要 Debug 復現他的問題,要跟他討論,很費時間,所以該如何平衡這個時間呢?如果所有工程師都在花時間在這裡解決這些問題的話,很可能會影響到我們正常的產品開發。
因此,我們現在有一個定期輪值的機制,即前端或後端會分出一個人力來在一段時間重點跟蹤這些專案,他的時間會分配得比較多,使得其他人在社群答覆上面受到的影響少一點,以此來做正常的專案迭代。這是我們目前的一個做法,還在調整中,後面如果還有更好的解決方式的話大家也可以去討論。

第三,如何將產品和技術理念國際化。現在我用中文跟大家交流,但如果在更廣闊的國際平臺上用英語,就是用或寫文章或是做演講的話,對我們自己的語言能力是一個挑戰。很多人之前沒有重視這方面,但我覺得這是讓其他使用者對你的專案產生信任的很重要的一步。可以透過這些瞭解你對產品的態度很重要。

第四,就是社群的規則。這一點我們現在還在建立中,包括怎樣獎勵對我們貢獻比較大的人,我們希望建立成一種規則性的東西 —— 比如:你對我們產品有很大的貢獻,我們有實物的獎勵或給你有一些榮譽;如果你的貢獻足夠大,你又有興趣比較全職性的參與進來的話,我們會給你怎樣的身份來將你吸納進來。還有就是大家怎樣參與到專案方向性的討論中來,這是我們後面社群要去建立規則的一個重點。現在的討論還比較分散,但我希望我們能有一些定期的話題去討論,討論完後可以形成某些提案,大家可以去投票,去決定做不做,很多成熟的基金會是有這樣的機制的。

image.png

最後是我們專案的一個小廣告,大家如果想貢獻的話,可以一起來貢獻,不管什麼形式,哪怕是言語上的鼓勵也可以。

https://answer.dev
https://github.com/answerdev/answer
https://twitter.com/AnswerDev

這是我們的官網主頁,包括我們 GitHub 主頁及我們在 Twitter 的官方賬號,歡迎大家隨時與我們互動。

我的 ID 是 @joyqi,大家可以在各個平臺都可以透過該 ID 搜到我,歡迎大家和我聯絡!

相關文章