瀏覽器裡的黑天鵝:不可預知的前端變革點

doodlewind發表於2017-12-14

『黑天鵝』是這樣的事件:難以預測、衝擊性大,並且能馬後炮地事後分析。少數的黑天鵝事件幾乎能解釋這個世界上發生的所有事情。難道前端領域的演化也不是循序漸進,而是黑天鵝式的嗎?讓我們換一種角度回顧一下歷史吧…

不可預知的黑天鵝

審視一下你周圍的環境,回顧自你出生以來周圍發生的重大事件、技術變革和發明,把它們與人們此前關於它們的預期相比較,然後看一下它們中有多少是在預料之中的?看看你自己的生活,你的職業選擇、你與配偶的邂逅、你被迫離開故土、你面臨的背叛、你突然的致富或潦倒,這些事有多少是按照計劃發生的?

——《黑天鵝》

許多史書、傳記都以一種決定論的視角來闡述歷史演化的必然性,但實際上對於生存在當時的芸芸眾生而言,歷史上的巨大變革點往往在某個平凡的日子裡突然地發生,沒有一點點防備也沒有一絲顧慮。比如,當年一位準備離休當教授的江南老人,怎麼就突然去了北京呢?

我的這個經歷就是到了上海,到了 89 年的年初的時候,我在想我估計是快要離休了,我想我應該去當教授……我絕對不知道,我作為一個上海市委書記怎麼把我選到北京去了。

——?

技術的發展同樣存在著高度的跳躍性和不確定性。在幾年甚至幾十年一遇的時間節點上,會誕生出全新的技術,然後才是一段段的平穩增長。並且,新技術的誕生往往並不像 iPhone 釋出會那樣具備強烈的儀式感,而可能只是在平淡乃至質疑中揭開自己的面紗。下面,我們會把視野進一步聚焦到瀏覽器裡,來看看前端領域中幾個我們今天再熟悉不過的技術是怎麼誕生的,在當時又引起了什麼反響呢?

倉促降生的 JavaScript

90 年代中期是個神奇的時間段。在電影工業界,1994 年誕生的三部經典影片《肖申克的救贖》、《這個殺手不太冷》到《阿甘正傳》長期在豆瓣電影 Top 250 中位列前十。而到了 1995 年,三門新生的程式語言在今天更是牢牢佔據 TIBOE 程式語言排行榜中的前十,它們是 Java、PHP 和 JavaScript。

如果說 Java 表達了肖申克監獄的沉重,PHP 暗示了殺手裡昂的危險,那麼 JavaScript 在誕生之初或許體諒了阿甘的智商…多年後 JS 之父 Brendan Eich 在接受採訪時,是這麼表達設計 JS 的初心的:

我們準備向使用圖片、外掛和 Java applet 等元件構建 Web 內容的 Web 設計師和兼職程式設計師提供一種『膠水語言』。我們把 Java 當做高薪程式設計師使用的『元件語言』,而膠水程式設計師——即網頁設計師們——就可以通過一門指令碼語言來組裝元件並將互動自動化了。

所以,在 JS 作者本人看來,他所期望的前端工程師不過是『兼職程式設計師』和『膠水程式設計師』(原文 part time programmer / glue programmer)而已,這多少有些一語成讖的味道。為了讓實現這門語言的提議獲得 Netscape 管理層的認可,他在 1995 年 5 月,花了十天實現了一個原型。請注意這個時間節點,因為區區三個月後,Netscape 就以創造 IPO 記錄的姿態上市了。

在公司高速發展的歷史背景下,JS 的很多方面都有趕工的痕跡。在訪談中被問及語言發展過程中最頭痛的問題時,Brendan 也承認了這一點:

(最棘手的問題)主要是概念驗證的時間不可思議的短,並且在這之後語言設計就必須凍結了。包括實現內建物件在內,我開發直譯器的時間是大概十天。

如果 Brendan 知道這些匆匆凍結的基礎設計會在接下來的 20 多年裡影響百萬級的開發者和十億級的使用者的話,也許他會說服管理層多給他一點時間吧……這麼短的設計時間導致這門語言的基礎設計中存在著一堆歷史原因留下的技術債,比如語言里居然並存了 undefinednull 兩種表示『值不存在』的概念:

JavaScript 在設計時應用了 Java 將值區分為『原始值』和『物件』的做法。它也使用了 Java 表達『不是物件』的值,即 null。而根據 C(而不是 Java)的先例,null 在轉換到數值的時候會成為 0:

> Number(null)
0
> 5 + null
5
複製程式碼

而 JavaScript 的第一個版本是沒有異常處理的。這樣一來,一些未定義的變數和缺失的屬性就需要通過一個值來表示。null 本來很適合這個場景,但 Brendan 還想要滿足下面兩個條件:

  • 這個值不應該有對應到引用型別的含義,因為它不僅僅是物件。
  • 這個值不應該轉換到 0,因為這樣會使得錯誤更加難以發現。

結果,Brendan 加上了 undefined 這個概念來表達另一種形式下的『值不存在』。它會轉換成 NaN

> Number(undefined)
NaN
> 5 + undefined
NaN
複製程式碼

這就是 JS 中別 (chou) 具 (ming) 一 (zhao) 格 (zhu) 的 undefined 的由來了。這個特性在很多年來給很多開發者帶來了很大的痛苦。比如,一個 bug 在真正產生的那一行常常不會直接報錯,而是會產生一個 undefined 被直譯器接收。然後過了很久,在另一個地方會產生一個莫名其妙的報錯,告訴你 undefined 下不存在某某屬性,但其實錯誤根本不在這一行,而是在很早之前就發生了!這個特性放在今天來看絕對入不了 PL 界的法眼,不過只給你十天的話,你真的不會選擇這個更容易實現的設計嗎?

當然了,沒有任何一門語言生來就是完美的。然而在瀏覽器這個對前向相容有著極其嚴苛要求的領域,想做出任何語言特性上的 Breaking Change 都是非常困難的。像下面這個問題就已經是一個 feature 而不是 bug 了:

var obj = {}
typeof obj // 'object'
typeof null // 'object'

obj instanceof Object // true
null instanceof Object // false
複製程式碼

作為總結,現在我們有這些證據來直接或間接地證明 JavaScript 是一個倉促實現的產物:

  • 設計目標定位低端碼農。
  • 金主處於粗放增長階段。
  • 原型迭代花費時間極短。
  • 許多基礎特性實現潦草。

在網際網路這個連線超過 30 億人的巨大系統裡,應用層的唯一程式語言卻是一個充滿設計缺陷的趕工作品,實在是一件匪夷所思的事情——這也很好地體現了黑天鵝事件突然發生而影響深遠的特點。當然,Web 的重要性催生了無數後來者持續的創新,下面我們會挑選出這些創新中最廣為人知的幾項,來印證它們的黑天鵝性質。

面基現場的 jQuery

十二年前那個白色相簿的季節,如果你有幸在紐約參加了一場 BarCamp 線下交流會,你能想象到臺上這個叫做 John Resig 的小夥子安利的,連文件都還沒寫完的新輪子會在全世界超過 70% 的網頁裡執行嗎?

BarCamp 是一種由參與者相互分享的工作坊式會議,其議程內容由參加者提供,主題通常與網際網路、程式設計、開源相關。換句話說,這是一種小規模的技術交流會。BarCamp 會舉辦很多次,由很多演講者來分享很多不同的主題,以 jQuery 的影響力而言,它可能是這類活動中誕生的輪子裡最著名的 Big Thing 了。不過,紅極一時的 jQuery 在釋出時,甚至只是作者本人的幾個分享主題中的一個而已。根據 John Resig 自己的陳述,在那場 BarCamp 中他也沒分享什麼別的,大概三件事:

  • 講了一個叫做 ideaShurb 的實時協作應用 Demo。
  • 講了一個叫做 Feed Pile 的新網站產品,用來匯聚熟人的資訊流。
  • 講了一個叫做 jQuery 的新輪子,可以改進用 JS 控制 HTML 的方式。

如果說還有一點什麼成績,就是額外講了一個對社交網路思考的 PPT,還有提出了一個付費社交的 idea 也是很大的。不過最主要的就是這三件事。

在當時,編寫 JavaScript 意味著不停地在相容性上踩坑:你需要支援 IE6 和 Firefox,而穀人希的 Chrome 五年後才釋出。jQuery 很快受到了膠水程式設計師前端開發者們的普遍喜愛,到今天來自近 300 人的超過 6000 個 commit 記錄證明了它的火熱程度。jQuery 還建立了基金會,有許多志願者繼續維護。

從 jQuery 的例子裡我們能夠看到,一個變革性技術的起點可以有多麼小。jQuery 並不是某個公司或組織推進的專案,作者本人在當時更沒有 all-in 開發(John Resig 本人還是一位創業者和浮世繪研究者,在基金會成立後基本上退出了專案的維護)。而回到今天,現在我們還有誰知道 ideaShurb 和 Feed Pile 呢?我們非常有理由相信,作者本人一定希望他分享的這三個專案都能做起來,然而最後留下來乃至改變上百萬人工作方式的,只有 jQuery 這一個。在今天,有許多文章有著『當時的 Web 面臨著相容性問題,所以 jQuery 的出現是歷史的必然』這樣的觀點。不過只要你瞭解了它的誕生過程,就會發現黑天鵝的偶然性和不確定性才是這些專案中唯一的共性。

在這一節的最後,讓我們懷念一下當時的 jQuery 首頁吧。那時候天還是藍的,水還是綠的,北京的房價還只要 8000 一平……

jquery-debut

飽受質疑的 React

當我們開源 React 的時候,最早收到的反應是有疑問的。

在 React 開源一週年之際,其官方部落格上輕描淡寫的一句話背後,是其誕生之初社群普遍性的質疑。讓我們看看 Reddit 上的人們最早對於 React 開源的訊息是如何回應的吧:

讀了他們的文件,我都根本不知道最簡單的示例是想幹嘛。

只有我覺得這個看起來又亂又笨重嗎(還有個新語法要學)?這個比起 Angular 來有什麼好處嗎?

Facebook 的庫能給 Facebook 用,不代表它適合其他人。

臥槽好嚇人,為什麼會想在程式碼里加 更多的 標記呢?

有那麼一秒鐘我在想今天是不是 4 月 1 號。它破壞了太多約定了,註定拉仇恨。我歡迎多樣性,不過這個看起來肯定不好。

把 HTML、XML 和 JavaScript 混在一起的做法讓我感覺回到了 JSP 的年代。當你在一個檔案裡存在五種語言和語法的時候,判斷游標位置是哪種語言都是一個 NP 難的問題。算了吧,除非真有啥區別,要不然我還是用 Angular。

HTML 混在 JavaScript 裡?不了謝謝。

看起來花了十個億啊。

醜。

Reddit 上最熱門的幾十條評論中,幾乎有 90% 以上都是負面意見。有意思的是,剛好在這一年,知乎上對阿里雲王堅博士的評價也是一邊倒的差評。

在公開的資料中我們能知道的是,React 最早是 JS 版的 XHP(這是一種 Facebook 的 PHP 方言),由於 XHP 和客戶端 JS 程式碼混編的不便,一名工程師向經理申請到了六個月時間來把它完全遷移到 JavaScript 上。時至今日,它已經有了幾萬個 react-xxx 周邊外掛、近萬 commit 和上千貢獻者,是前端社群中的超級巨星。

React 代表的就是另一種型別的技術創新了。它的確打破了很多『最佳實踐』和思維定式,也帶來了非常多的爭議,但它背後的理念和正規化的確引領了前端社群的一輪技術進步。在這個例子中最有意思的地方在於,一個 2013 年的膠水程式設計師前端開發者初次接觸它的時候,90% 以上的第一印象是『這 TM 什麼玩意』,沒錯,那時的主流民意也覺得比特幣太貴了…在預測未來的能力上,我們經常錯得離譜卻還自以為是

關於 React,最後還有一個細節很值得一提:它是本文中唯一一個沒有明確作者的輪子。我們都知道 React 是 Facebook 公司的產物,但那個申請到六個月時間造輪子的工程師是誰呢?React 的所有新訊息都是通過 Facebook 官方部落格釋出的、原始碼裡的 AUTHORS 是字母排序的、react-basic 的初始設計文件也沒有作者的提交記錄…我們最後還是找到了這位大牛 Jordan W 的 Github,不過和 React 團隊裡群星璀璨的網紅們比起來,他卻連照片都不放一張…結合國內前端社群關於 Vue 和 Angular 的大撕逼與 React 的爭議性,我們似乎可以理解作者隱姓埋名的苦衷了…

生逢其時的 Vue

上文的介紹的這些輪子,都有著自己牛逼閃閃的地方:JavaScript 使得瀏覽器中的富互動行為成為可能、jQuery 發明的 DSL 大大簡化了 DOM 操作、React 的程式設計正規化顛覆了開發者的思維模式…而到了 Vue 這裡,我們卻很難找到一個『好用』之外,它在技術上的顛覆性閃光點。不過,既然它的熱度在國內已經蓋過 React,它也定然有自己的獨特之處。

和 React 相比,Vue 的亮相可以說是默默無聞了。在 Hacker News 上,作者 Evan You 初次釋出 Vue 的帖子獲得了 54 點數和 26 條評論。作為對比,React 連換個許可協議都獲得了 2280 點數和 498 條評論。

雖然初次釋出時話題性沒有 React 那麼強,但是 Vue 的傳播和口碑卻相當的好,在釋出後的第一週內就獲得了 2w+ 的官網瀏覽量和 600+ star。三年以後的今天,它已經幾乎成為中國開發者業務開發的首選框架了。Vue 興起的過程已經老生常談,在此按下不表。在這一節裡,我們希望思考的問題是:為什麼就在近期,有大量的前端開發者轉向 Vue 呢?為什麼 Angular / Avalon / Knockout 這些類似的 MVVM 框架沒有形成這樣的星火燎原之勢呢?

從技術角度上,筆者能夠想到幾個『合理』的理由:

  • 轉向 Vue 時國內已經可以普遍拋棄 IE8,而 Vue 的實現原理恰好最低支援 IE9。
  • Angular 1 效能不好,而 Angular 2 的 API 變更非常大。
  • React 的 JSX 長期被視為異端,全家桶不好配,中文化支援也沒有 Vue 好。
  • Knockout 和 Avalon 缺乏現代的工程化支援,維護乏力。
  • ……

所以這些理由有道理嗎?它們不過都是純粹的馬後炮而已!這些理由都不過是我們基於『Vue 非常火』的現實,去正當化『Vue 為什麼能火』的合理性而已。毫無疑問,Vue 的框架設計是第一流的,不過,Vue 的普及程度是某些大廠內部框架的幾十倍,是否意味著它的程式碼質量就比這些同時期的框架好上這麼多倍呢?我們沒法量化比較這一點。不過,這裡有一個例子可以作為類比:

如果你是個音樂愛好者,那麼在沒有唱片的時候,你可能會花錢到本地的劇院花 100 刀聽本地小樂團的音樂會。而在唱片流行後,你可以只花 10 刀就能聽到世界第一樂團的音樂,這時候你去本地小樂團的音樂會的意願還會一樣強嗎?對於資訊資源,存在著非常強的馬太效應,而開源也在程式設計領域大大加強了這種效應。類比到前端領域裡,種種 React 和 Vue 等框架的替代品有多少真正應用到了生產環境呢?黑天鵝的巨大影響力很大程度上來源於這種『贏家通吃』的集聚效應,而 Vue 則是這個領域中不可多得的勝利者。

到這裡為止,我們已經看到了瀏覽器領域裡幾個關鍵技術的誕生,和我們的想象之間所存在的不同:JavaScript 實現得非常草率、jQuery 只是個微小的業餘專案、React 誕生之初飽受質疑、Vue 的設計並沒有多少顛覆性…然而它們已經不會被歷史遺忘了。所以下一個變革點在哪呢?如果黑天鵝能夠被預測,那它就不是黑天鵝了。

後記

人吶就都不知道,自己就不可以預料。一個人的命運啊,當然要靠自我奮鬥,但是也要考慮到歷史的行程。

行文至此,筆者有了一些額外的想法:文中涉及的開發者毫無疑問都是社群中的精英,但做出巨大貢獻的他們,在技術水平上就一定是最優秀的嗎?個人願意相信,在百萬級的開發者中,必然還存在著許多低調的大牛們,他們的專案所需工作之艱深,所遇到的挑戰之困難不會亞於上面的任何一個專案。不過,黑天鵝只有那麼幾隻,聚光燈的範圍也只有那麼一點,對於絕大多數勤勤懇懇的開發者,黑天鵝的機會都是可遇而不可求的。

所以我們該有怎麼樣的態度來面對技術演化的黑天鵝性質呢?玉伯 dalao 的簽名非常有借鑑意義:『因上努力,果上隨緣』。達到開發明星專案水平的同學有很多,但革命性的專案有太多不確定性,我們能做的也就是踏實地去學習和進步,然後耐心地等待吧。換句話說,這就是所謂的『且行好事,莫問前程』了。當然了,請不要把這個態度和膠水程式設計師們心安理得地編寫增查改刪的業務邏輯混為一談哦 ?

鑑於作者對前端的瞭解有限,因此本文只涉及了幾個前端領域中老生常談的例子而已。如果大家有勘誤或更好的想法,歡迎在 Github 或評論中提出,謝謝。

References

相關文章