Visual Studio Code 的目標是做一個 Lightweight Editor,通過的擴充套件 api,讓使用者在 VS Code 中達到和 IDE 中接近的開發體驗(效率)。
不過很多群眾對 VS Code 有諸多誤解,我先來一一解答
“VS Code 師出 VS,是 VS 找了一群人來重寫的,複用了很多 VS 的程式碼,等等“。很抱歉,並不是這樣,半毛錢關係也沒有。VS Code 的核心程式碼,也就是 Microsoft/monaco-editor 是 Erich Gamma 2011 年加入微軟後,招聘的一支“全新”的隊伍進行開發的。Monaco editor 從一開始就是一個 browser based editor,早期一直服務於各個微軟系統中(比如 Visual Studio Online,OneDrive online)。招聘的這支隊伍對於 Erich 來說並不是新的,因為大部分成員都是原先 IBM 的老部下,其中幾位大爺跟著 Erich 擼了二十多年程式碼了。“VS Code 是 Atom 的復刻,是對 Atom 的魔改,是 Atom 的一個主題!”。很抱歉,並不是這樣,但還是有幾毛錢關係的。Monaco Editor 在經歷幾年的高光期,進入了一個小小的黑暗時代。這時候團隊成員開始調研將 Monaco Editor 做成桌面應用,和 Atom 一樣,我們首先關注到的就是 node-webkit。必須說 node-webkit 是業界的一縷清風,給這個產業帶來了太多的可能性。當然最後我們選用了 atom-shell,也就是後來的 Electron。但就是這個 atom-shell,給大家帶來了以上的誤導。
開源運動愈發受到網際網路科技公司的喜歡,曾經視開源為毒瘤的微軟,也都大刀闊斧地擁抱開源了。參與開源的開發者也越來越多,GitHub 的活躍度也佐證了這種現象。
大型開源專案包含以下任意一個或多個特徵:
GitHub star 數量 1000 +每週都可以接收到多個 issues 或 PR有一些公司或其他專案在生產環境中使用任意一個或多個包管理系統中下載量巨大在專案所在領域中擁有較大關注度可以從以下幾個方面進行回答。
先介紹你的專案,用來幹什麼的?在開發和維護的過程中遇到過哪些值得一提的事?有沒有什麼奇葩的 issue 或者 PR?對你的生活或者工作有沒有造成影響(好的,壞的)?伯樂線上摘編了兩位朋友的回答,均已獲得授權。
1. rebornix 的回答分享(link),伯樂線上已獲授權
加入 Visual Studio Code – Code Editing. Redefined 快一年,趁這個機會聊一聊開發和維護這個專案的感受,如果大家不反對這是一個 大型 開源專案的話。以下為個人理解,不代表公司也不代表團隊。
專案
Visual Studio Code 的目標是做一個 Lightweight Editor,通過的擴充套件 api,讓使用者在 VS Code 中達到和 IDE 中接近的開發體驗(效率)。
不過很多群眾對 VS Code 有諸多誤解,我先來一一解答
“VS Code 師出 VS,是 VS 找了一群人來重寫的,複用了很多 VS 的程式碼,等等“。很抱歉,並不是這樣,半毛錢關係也沒有。VS Code 的核心程式碼,也就是 Microsoft/monaco-editor 是 Erich Gamma 2011 年加入微軟後,招聘的一支“全新”的隊伍進行開發的。Monaco editor 從一開始就是一個 browser based editor,早期一直服務於各個微軟系統中(比如 Visual Studio Online,OneDrive online)。招聘的這支隊伍對於 Erich 來說並不是新的,因為大部分成員都是原先 IBM 的老部下,其中幾位大爺跟著 Erich 擼了二十多年程式碼了。“VS Code 是 Atom 的復刻,是對 Atom 的魔改,是 Atom 的一個主題!”。很抱歉,並不是這樣,但還是有幾毛錢關係的。Monaco Editor 在經歷幾年的高光期,進入了一個小小的黑暗時代。這時候團隊成員開始調研將 Monaco Editor 做成桌面應用,和 Atom 一樣,我們首先關注到的就是 node-webkit。必須說 node-webkit 是業界的一縷清風,給這個產業帶來了太多的可能性。當然最後我們選用了 atom-shell,也就是後來的 Electron。但就是這個 atom-shell,給大家帶來了以上的誤導。最後,我們一定要尋根問祖的話,VS Code 應該是師出 Eclipse(同志們,哎你們怎麼扭頭走人了,別怕,我話沒說完呢)。團隊核心的幾位大爺,早年就跟著 Erich,在寫了幾個 Editor/IDE 之後,創造了 Eclipse。正是因為見證了 Eclipse 的興衰,所以這一次在設計 Monaco/VS Code 的時候,才會如此的剋制。Extensibility 不好嗎?當然好,但是 Eclipse 的弊端已經在一些競爭對手身上出現啦。
開發/維護
我 13 年加入微軟後,就開始接觸到 Monaco 了。在使用的過程中踩了一些坑,研究過程式碼,做過好一些擴充套件。所以在 VS Code 正式開源後以及上線 Marketplace 後,我就開始動手寫一點外掛和發 Pull Request。去年五月得空和團隊結對程式設計了兩個禮拜後,就加入了 VS Code。
VS Code 的開發幾乎完全是公開的。早期我們還通過 User Voice 收集反饋,但我們早就把它關掉了,所有問題的處理都放在 GitHub 上。我們的 Yearly/Monthly plan 都以 issue 的形式呈現 Microsoft/vscode ,而我個人正常的開發節奏是這樣的:
計劃
在上一個 milestone 快結束、新的 milestone 開始的第一週,和老闆溝通新的 milestone 自己想做的功能。以及自己要不要休假。
Debt Week
我們把新 Milestone 的一週當作 debt week,集中處理一些技術債,以及為一些外掛做點微小的貢獻。我一般會花一點時間在 Vim 外掛以及我自己的 Ruby 外掛上。
開發
這之後就是兩到三週正常的開發。每天起床得先把自己頭上的新 issue 都 triage 一遍,遇到緊急的得先修,不然就繼續完成自己的 feature。
Inbox Tracking
我加入團隊的時候,我們只有 1700 個左右的 issue,現在已經破 4000 了(大部分都是 feature request)。GitHub Inbox 在這種情況下是無用的,我們的做法是每週會有一名同事,負責 GitHub 的新 issue,assign 給合適的 owner。我已經當過三次 Inbox Tracker,只能用可怕來形容。每天一睜眼就是一百多個 issue 要處理,一點都不想起床。
Endgame
我們在 milestone 的最後一週 endgame 會對新 feature 進行各種花樣的測試,對這個 milestone 關掉的所有 issue 進行驗證。全部完成後,每個成員書寫自己負責部分的 release note。最後 Endgame master 會到後臺網站釋出新的 Stable 版本。
印象深刻的事
當之無愧就是《VS Code uses 13% CPU when idle due to blinking cursor rendering》。VS Code 是基於 Electron 的,而 Electron 則基於 Chromium。這樣的話,Chromium 的鍋有時候得我們來背。
VS Code 裡的編輯區域並不是 textarea ,全都是 mock 的,這也是主流做法,Ace、CodeMirror、Atom 無不例外。理由也很簡單,要實現Tokenize、高亮、Partial Render、Line Wrap,自己控制渲染肯定是最方便的。為了儘可能模擬 textarea,我們模擬了游標。最開始這個游標的跳動,是通過 Java 來控制游標的 opacity。後來社群給我們貢獻了一個 pull request,使用 CSS animation 來調整 opacity。實現上來說肯定是比 Java 版本更優雅,同時也提供了四五種不同的游標跳動的選項。
但誰知道,Chromium 對於 CSS Animation 是有巨大的坑的。比如你寫的 animation 是每秒改變一次 opacity,但是 Chromium 會根據重新整理率(比如 60hz)來檢測頁面上的 animation。雖然我不知道 Chromium 做了什麼,但是你可以看到每16ms,Chromium 就會吃掉一點你的 CPU 和 Battery
當時我剛吃完晚飯,但是由於這個事情在我的防區,我只好開電腦 troubleshoot。最後發現是 Chromium 的 bug,開了兩年多了,我只好告訴 Jo Liss,這鍋我們不背,但是我們會修的。
結果之後好事者把事情捅到了 HackerNews,瞬間成了當天大新聞,還上了 TheRegister 小報。所有人都開始討論使用 Browser 技術做桌面應用是不是正確的選擇,撕的不亦樂乎。
你們撕的倒是開心了,我那幾天給各種老闆解釋什麼是跳動的游標,忙的跟狗一樣。好在後來 Chromium 的 PM lead Paul Irish 留言表示這是他們的 bug,算是完美收官了。
有沒有什麼奇葩的 issue 或者 PR?
你們猜大家看到中文寫的 issue 會找誰來翻譯?有些朋友提交了 PR,根本不管你給的建議,自顧自的更新修改。這樣的 PR 根本不可能 merge,但是我們給的儘可能禮貌地建議,有些朋友真的把它們只當成建議。。。再一次說到跳動的游標,這個始作俑者是社群的朋友,看起來也是非常 neat 的實現,誰知道就踩了 Chromium 的坑呢。。。關於中文 issue 的問題,VS Code contribution guide 寫的是比較清楚的,請大家用英文提問。但是鑑於中文使用者量巨大,加之人總有英文不夠用的時候,VS Code 也會經常看到中文問題。我有這樣一些想法:
寫中文我個人覺得問題不大,畢竟 GitHub 是我們幾乎唯一的反饋渠道,不能要求使用者必須會英文。寫中文的確增加了我本人的工作量,所以能寫英文,還是儘量寫。但如果你覺得需要嚴重的 Google Translate 的幫助,我建議還是寫中文,並且 cc 我。不然可能翻譯出來最後誰也看不明白,或者誤解。我老闆問我,為啥中文 issue 幾乎把所有東西都寫在標題裡,然後 issue 描述留空。我真的不知道該如何回答。如果用中文寫 issue,並 cc 我,請保證把reproduce steps 寫好,一步一步用中文寫清楚,這總沒難度吧?如果第四步做不到,還要我解決問題,請考慮請我喝啤酒吧。生活
大家都喜歡開源,但開源貢獻者大部分時候是在做義務貢獻。這麼來看在微軟搞 VS Code 就是一件愉快的事情,畢竟有人給你付工資讓你做 open source。而且再也不用上班搞一套程式碼,回家之後私下自己在 GitHub 上面逛遊,搞別的專案,上班和下班後可以在同一塊土地上耕耘。
當然這樣缺點也很明顯,就是生活和工作往往難以分開。工作是一週五天,一天八小時,但是 GiHub issue 從來都是 7*24。遇到棘手的問題的時候,很難放任不管,哪怕已經回了家。不過也正是因為專案的特殊性,我們組還是有比較好的 remote 和自由工作時間的文化的。
zcbenz 的回答分享(link),伯樂線上已獲授權
這次籍著Electron 1.0釋出的機會,說說我自己維護兩個大型開源專案的經歷吧,分別是 node-webkit(也就是現在的NW.js)和Electron。
前者是幾年前自己單打獨鬥,在公司0資源投入的情況下從兩百多star一直做到好幾千star,具體數字已經忘掉了,只記得當時在C++專案排行裡做到了前十,直到自己另起爐灶。而後者,則是披著GitHub的光環,有著公司熱心的投入,毫無障礙一路跑到了現在的三萬多star。
(使用Star History生成的star數統計圖)
如果大家有接觸過前端或者桌面端的開發,那麼很可能有聽說過NW.js的大名,node-webkit就是其改名之前的稱呼。
但絕大部分人可能並不知道,node-webkit在最初發布的時候(2011年),並不是面向開發桌面應用程式,而是一個Node.js模組,可以建立一個WebKit視窗。神奇的一點是,你可以在這個視窗的頁面裡呼叫Node.js的模組。
Node.js程式碼:
varnwebkit= require("nwebkit")
nwebkit.init({"url": "index.html"},function(){
nwebkit.context.run("")
})
index.html程式碼:
<html><body>
<pid="output"></p>
<>
require("fs").readdir(".",function(err,files){
varresult= ""
files.forEach(function(filename){result+= filename+ "<br/>"})
document.getElementById("output").innerHTML= result
});
</>
</body></html>
大家可以在NW.js的webkitgtk分支裡找到node-webkit的原始實現,甚至嘗試重新build一遍。不過這個模組一直未能穩定下來,玩具的味道更多一些。
再後來,原作者 rogerwang 對其進行了改進,從使用WebKit改成了呼叫Chromium Embedded Framework(簡稱CEF),一個可以把Chromium嵌入應用程式的庫。這個程式碼一直沒有正式公佈,但大家可以在node-webkit的cef分支裡找到。程式碼的另一部分是針對Chromium的幾十行補丁,將Chromium的message loop替換為libuv,但是NW.js在開發過程中對程式碼庫進行了很多次rebase操作,原始程式碼已經找不回來了。
找個實習生來開發
node-webkit的原作者rogerwang在Intel開源技術中心工作,雖然Intel在大家心目中可能更多是個賣CPU的,其實在開源方面也非常熱心,甚至提供開源方面的實習工作。
在2012年的夏天,一則Intel的實習資訊吸引了我的注意,上面說Intel需要一名熟悉Node.js的學生來進行node-webkit的開發。我投了簡歷,也很幸運地開始了node-webkit的開發。
Content Shell
我最初的工作是對node-webkit的cef分支進行改進,但是很快就發現很難繼續進行開發了。CEF提供了自己的一套API來包裝Chromium的內部API,而Node.js則是直接呼叫V8的API,如果想要把CEF和Node.js合併到同一個專案,困難重重。
於是我乾脆將node-webkit推倒重寫。新的程式碼基於Content Shell,一個Chromium程式碼庫內的最小化瀏覽器實現。
重寫後的結果非常不錯,我得到了一個可以呼叫Node.js模組的瀏覽器實現。基於這套程式碼我釋出了node-webkit v0.2.1。
把node-webkit進化成桌面開發利器
至此node-webkit已經變成了一個獨立的瀏覽器,而不再是Node.js模組。為什麼不把它變成一個使用Java和HTML開發桌面應用的工具呢?後面幾個月我開始對這個想法進行嘗試。
首先我模仿遊戲框架LÖVE framework為node-webkit實現了一個打包系統,可以把應用直接附加到exe上:
(node-webkit的打包系統,來自我自己的PPT)
接著這是各種細節上的完善:比如利用package.json檔案來描述應用;給視窗加工具欄;拓展DOM來提供API;取消瀏覽器的安全系統;等等。當然還有無休無止的bug修復。
其中最有挑戰性的一點是支援Node.js的native module,我對Chromium打上各種補丁來暴露V8和OpenSSL的API,給Node.js打補丁好解決OpenSSL和NSS之間的符號衝突,提供自定義的node.lib來支援Windows,最後還要提供適用於node-webkit的編譯工具。
完成這些工作以後我釋出了node-webkit v0.2.5。
提供構建GUI的API
這時我的絕大部分工作都在圍著瀏覽器轉,而由於瀏覽器自身的侷限性很多功能我都沒法提供。比方說瀏覽器裡就沒法建立系統原生的選單。(當然今天已經有了HTML5 Menu標籤,而當時是2012年。)
於是我想到增加一個新的內建模組,用來提供對視窗、選單等系統API的繫結,也就是:
require("nw.gui")
如果你有使用過NW.js的話,你應該很熟悉這一套API。
經過幾個月的完善後,我釋出了node-webkit v0.3.6,這也是由我維護的最後一個版本。
node-webkit的推廣
雖然node-webkit屬於Intel,但其更多屬於rogerwang的個人專案,那時候這個專案在GitHub上也還掛在rogerwang的賬戶下。所以當時除了我自己一個人,沒有其他任何來自Intel的資源投入。
而像node-webkit這樣的框架類專案,只有擁有使用者,才會有生存下去的意義,所以在開發node-webkit的半年時間裡,我也一直有在積極推廣。
首先是到處發帖子宣傳node-webkit的好處,一大陣地是Node.js的郵件列表。每次有新版本我就會過去釋出公告,回答問題,與人撕逼。其次則是編寫範例應用,讓新手快速入門,讓其他人相信node-webkit的能力。最後則是去技術會議宣傳,讓大家知道node-webkit這個東西。
當然最重要的還是認真回答Issues裡的問題,努力修復bug增加功能。
我的努力最後也得到了非常好的回報,在我結束node-webkit開發的時候,專案在GitHub上獲得了數千個star,排到了C++專案排行的前十。
第一個使用者
另外值得一提的是node-webkit的第一個使用者,Light Table 編輯器。這個編輯器的作者 ibdknox 很大膽地使用了node-webkit來進行開發,當時為node-webkit迎來了非常多的關注,也給大家吃了一枚定心丸,為專案推廣助力巨大。
幾年後Light Table又從node-webkit遷移到了Electron,當時好似好友重逢,感觸良多。
工作的轉移
在我為node-webkit工作半年之後,2012年底,這個專案開始吸引越來越多的注意力,也開始引起Intel一定程度的注意。rogerwang得到了機會放下其他的工作,開始全職維護node-webkit。
(GitHub的程式碼貢獻表)
但之後正當node-webkit冉冉升起之時,我卻徹底失去了node-webkit的自治權,開始收到命令去完成指定的開發工作,被禁止隨意去增加功能,也不允許去隨意修復bug,而釋出新版本、和客戶交流的工作也被轉移給更高級別的工程師手上。正如一個大公司裡的螺絲釘。
可能這種開發方式才是大公司的常態,我也不想抱怨任何人,但是抱歉,我只是一點也忍不了。
為GitHub而戰
在我進行node-webkit開發的同時,GitHub正在祕密開發Atom編輯器。我瞭解到GitHub正在尋求一種使用HTMl和Node.js來開發桌面應用的方式,於是聯絡到Github
的工程師nathansobo,表達了為GitHub工作的意願。
所幸node-webkit已經為我自己博得了足夠的名氣,在一面未見的情況下,我們敲定了協議,我需要將Atom遷移到node-webkit之上,並且提供支援工作。
於是2012年底,我結束了在Intel的實習,開始為GitHub作為contractor工作。
一個更好的桌面應用框架
在我加入Atom的開發時,專案還基於CEF。我們嘗試了將Atom遷移到node-webkit上面,但是最終效果並不是很好,node-webkit當時並不穩定,而且API有太多的坑。
於是我開始重新考慮node-webkit的API設計,發現如果想要支撐大型應用,我不得不做出很多結構性的改變,而這些改變與其修改node-webkit,不如重寫更加實際。在和GitHub討論之後,我開始編寫一個新的桌面應用框架,當時的名稱叫做atom-shell。
有興趣的同學可以去了解一下我們究竟做了哪些改變。
左右互搏
後來,經過長時間的開發,atom-shell最終開放了原始碼,而與此同時node-webkit 已經吸引了非常多的注意力和使用者,我開始了和自己的競爭。
再之後node-webkit改名為NW.js,而atom-shell則改名為Electron。
(Electron 1.0)
說完了從node-webkit到Electron進化的歷程,最後說說維護開源專案的體驗吧。
和普通專案不同,開源專案幾乎所有的使用者都來自公司外部,取決於專案的受歡迎程度,每天都會受到相當大數量的郵件。就我自己而言,來自GitHub的通知郵件每天數量在50封左右,需要花1到3小時左右一一消化回覆。很多issue要去仔細重現,一些話題也需要大量的討論,很費神。甚至會有troll過來破壞所有人的心情。
維護專案的另一項工作,是稽核pull request,和維護node-webkit時不同,Electron的使用者群要大很多,所以每天都會收到pull request,其中不乏高質量的程式碼。但多數時候程式碼都不能直接合並,要麼設計不合理,要麼程式碼不合規範,更多地則是引入新bug。所以每個pull request都需要細心檢視,還少不了和貢獻者大量的討論。
於是,做完這些工作以後,留給寫程式碼的時候反而少了很多,也是沒有辦法。但對於一個開源專案而言,這些瑣碎的工作其實非常重要,只要讓人感覺你的專案在被精心維護,才能不斷吸引更多使用者。一個維護不善的專案,哪怕初期因為種種原因吸引了很多使用者,一旦更好的替代品出現,使用者馬上會飛速流失。
生活上,因為是全職做開源,影響反而非常小。GitHub的遠端工作氛圍非常濃厚,我的大部分工作時間也是在家裡而不是辦公室裡,所以多數時候是想寫程式碼了便開始工作,不在狀態就把工作放在一邊去做做喜歡的事,以此用有限的時間維持非常高的工作效率。
但開源會給自己帶來另一個問題,責任感。一個沒人用的專案,棄坑不過是一轉念的事情,但是當越來越多人開始用你的專案,甚至有創業公司把未來壓在你的專案上,責任感會越來越重,你唯一的選擇就是將專案繼續維護下去,無法棄坑,直到更好的技術出現。
不知道我未來還會維護Electron多久,不過就過去幾年來看,還挺開心的,應該還會繼續做下去吧。