
如果您和我一樣,您可能每天都在使用許多開源工具,卻沒有思考它們是如何開始的。很少有專案分享其創建的「原因」:它們試圖解決的實際問題以及何時首次遇到該問題。當然,您可以在不了解開源專案的起源故事的情況下從中受益,但我總是覺得聽到這一切是如何開始的很有趣。
我最近意識到我從未分享過 ESLint 的起源故事。我曾在之前的文章中分享過我在過程中做出的一些決定,但從未分享過最初的連鎖反應以及導致 ESLint 創建的原因。您將會看到,ESLint 的創建並非透過神來之筆或靈光乍現,而是透過一系列最終促成 ESLint 創建的事件。
這個錯誤
當我還在 Box 工作不久時,一位隊友正在處理一個奇怪的錯誤。一位客戶回報在使用 Internet Explorer 7 (我們可能是在當時仍在支援 IE7 的最後幾家公司之一) 中的網頁應用程式時遇到了問題。一位開發人員顯然在某些 JavaScript 程式碼中使用了原生的 XMLHttpRequest
物件,而不是我們內部的封裝器。這對任何其他瀏覽器來說都不是問題,而且在內部使用 IE7 進行測試也沒有問題。問題發生是因為客戶有一個內部安全策略,禁用了 Internet Explorer 中的 ActiveX,而且由於 IE7 中原生的 XMLHttpRequest
物件實際上只是 ActiveX 物件的封裝器,因此也被封鎖了。
解決方案很容易,只需確保每個人都知道要使用內部的 Ajax 封裝器,而不是原生的 XMLHttpRequest
物件。但是我們如何強制執行這一點呢?事實證明,Box 的建置系統中包含一個 JavaScript「linter」。我之所以用引號括住 linter 這個詞,是因為它實際上只是一系列針對 JavaScript 程式碼運行的正規表示式。對於這種情況,我的隊友為「XMLHttpRequest」新增了一個正規表示式,這就是解決方案。如果有人試圖提交符合該模式的 JavaScript 檔案,建置就會失敗。
以我的經驗來看,在原始碼上使用正規表示式從來都不是一個好主意。我希望在建置過程中能有更好的方法來進行像這樣的檢查。我認為一定有人已經解決了這個問題,所以我開始尋找解決方案。
可能是 JSHint 嗎?
我做的第一件事是發電子郵件給當時 JSHint 的維護者 Anton Kovalyov[1]。我記得讀過一篇部落格文章[2],其中說 JSHint 計劃支援外掛程式,但找不到任何關於該功能已實作的資訊。從過去為 JSHint 貢獻以及為 Yahoo 的一個專案修改 JSLint 的經驗來看,我知道 JSHint 最初並未設定為支援外掛程式,而且如果沒有正式支援,就不會有簡單的方法來修改 JSHint 以實現我想要的功能。
Anton 告訴我,外掛程式提案已經停滯不前,而且看起來不會實作。我感到很失望,因為這似乎是解決問題最直接的路徑。我感謝了他,並請他如果我創建了一個符合我需求的 linter,請不要介意。我想支援 JSHint,但我覺得這是一個需要解決的問題,無論有沒有 JSHint。
靈感
在深入研究 Box 的建置系統後,我發現除了臨時的 JavaScript linter 之外,實際上還有一個 PHP linter 在運行。然而,PHP linter 比 JavaScript linter 複雜得多。PHP linter 沒有使用正規表示式,而是將程式碼解析成抽象語法樹 (AST),然後檢查 AST 以找出要報告的模式。
當我讀到那些程式碼時,我可能一直在搖頭說「是」。我立刻意識到這正是我需要為 JavaScript 做的事情。如果可以將 JavaScript 解析成 AST,然後檢查 AST 以找出問題就好了。
基礎工作
當這些想法在我腦海中盤旋時,我邀請 Ariya Hidayat[3] 到 Box 做一場關於他喜歡的任何主題的演講。碰巧他做了一場關於 Esprima[4] 的演講,Esprima 是他用 JavaScript 寫成的 JavaScript 解析器。在那次演講中,Ariya 討論了擁有 JavaScript 的 AST 表示的用處,並參考了幾個已經建立在 Esprima 之上的工具。這些工具包括用於遍歷 AST 的 estraverse 和用於作用域分析的 escope,兩者都是 Yusuke Suzuki 編寫的。
隨著 Ariya 繼續演講並舉例說明 AST 可以解決的各種問題,一個新工具的想法在我腦海中形成了。我認為應該有一個工具可以執行 Ariya 提到的所有評估,這是很有道理的。畢竟,它們都只是為了不同的目的而使用 AST。為什麼不讓它們都使用一個 AST 呢?
開始
很大程度上歸功於 Esprima、estraverse 和 escope 的可用性,我才能在幾個週末內組裝出 ESLint 的第一個原型。對我來說,這三個實用程式代表了我創建一個新工具所需的一切,這個新工具可以輕鬆地在 JavaScript 程式碼中找到問題模式。如果我必須從頭開始創建這些工具,我毫不懷疑 ESLint 今天不會存在。在這些工具的基礎上,我能夠快速迭代,最終,您今天所知的 ESLint 工具誕生了。
(我覺得有必要指出,當時不只我一個人想要創建一個基於 AST 的 linter。JSCS[5] 也在大約同一時間開發中,而現任 ESLint 維護者 Ilya Volodin 在發現 ESLint 之前也在開發自己的專案。如果當時我沒有想出像 ESLint 這樣的東西,無疑也會有其他人想出來。多虧了 Ariya 和 Yusuke,所有的組件都已經存在,只是需要有人以有用的方式將它們組合在一起。)