
起因是我近日對 Atom 編輯器 的架構(gòu)好奇,就去讀了 Atom 和 Electron 的誕生歷程。然后順藤摸瓜的擼了 Node.js 等一些新的技術(shù)介紹,發(fā)覺 JavaScript 已經(jīng)不是 20 年前的毛頭小伙了……。它的觸角已經(jīng)伸展到幾乎所有的編程領(lǐng)域,成了名副其實的萬金油。本文就簡單梳理一下我這幾天看的無所不能的 JavaScript。
一、為表單驗證而誕生的 JavaScript
1995 年 Erendan Eich 為網(wǎng)景設(shè)計了第一版 JavaScript,主要用于表單校驗并獲成功。愛搞自己一套的微軟隨后也發(fā)布了自己的 JavaScript 方言 JScript。在其后幾年微軟和網(wǎng)景互坑互助,最終聯(lián)合推動了 JavaScript 的標準化版本—— ECMAScript 的確立。
2000 年左右隨著網(wǎng)站的高速發(fā)展, JavaScript 的價值越來越大,跟 HTML 和 CSS 并稱網(wǎng)頁三劍客。HTML 負責結(jié)構(gòu),CSS 負責樣式,JavaScript 負責行為。JavaScript 成為網(wǎng)頁必不可少的組成部分。
由于當時的機能限制,JavaScript 的使用場景有限,驚艷的動效都是由 Flash 負責。
二、前端制霸的 Ajax
1999 年,愛搞自己一套的微軟又在 IE 里做了個 XMLHttpRequest 的對象,卻沒有太重視,直到 2005 年,Jesse James Garrett 基于當時的一些 XMLHttpRequest 的應用,提出了 Ajax (Asynchronous JavaScript and XML) 的概念。之前,網(wǎng)頁向服務器提交數(shù)據(jù)(如發(fā)帖)就需要刷新頁面來顯示操作的結(jié)果,Ajax 通過異步交互實現(xiàn)無刷新的網(wǎng)頁更新方式,使得網(wǎng)站的交互操作更接近原生應用。還記得我在大學機房第一次用 Google Maps 的時候,感受它絲滑流暢的拖動和放大縮小,直接跪了,這才是黑科技!
這個時期,隨著 HTML/CSS 標準化,使得 JavaScript 具有了更重要的作用,比如操作 DOM 樹;機能提升使得 JavaScript 可以實現(xiàn)比肩 Flash 的動畫效果,而且更加輕量。所以涌現(xiàn)出以 jQuery 為代表的無數(shù)前端庫,極大的提升用網(wǎng)站的交互體驗和視覺效果。JavaScript 借著 Ajax 和 Web2.0 的浪潮,成為真正意義上的前端王者。
再之后則涌現(xiàn)出 MVC 架構(gòu)的 Angular.js,專注于表現(xiàn)層的 React.js 等框架,則是在“網(wǎng)頁即是應用”的路上持續(xù)進化。
三、魔爪伸向服務端的 Node.js
2008年,Lars Bak 在他的丹麥農(nóng)場為谷歌的 Chrome 寫了性能超群的 JavaScript 引擎 V8,V8 做為 Chrome 殺手級的亮點功能之一(沙盒和多進程是我認為的另外兩大殺手功能),對 Chrome 的成功功不可沒。
2009年,Ryan Dahl 借助 V8 的卓越性能和 JavaScript 天生的單線程特(缺)性(陷),腦洞大開的發(fā)布了 Node.js 項目。Node.js 是具有事件驅(qū)動,異步 I/O 特性的高性能,高并發(fā),輕量級 Web 服務框架。江湖中也不時傳來某公司用 Node.js 后少用了多少服務器的故事。
需要說明的是,Node.js 本身是基于 V8 引擎,也就是說它本身并不是用 JavaScript 編寫的,而是用 C++。Node.js 服務上面跑的腳本語言是 JavaScript 而已。Node.js + JavaScript 的組合就像 Nginx + Lua,一個是底層服務,一個是上層腳本。
后來,Node.js 變成了一個通用的 JavaScript 運行時,可應用的領(lǐng)域不僅限于服務器。如果說 Ajax 是第一個引爆點,幫助 JavaScript 奠定了前端老大的地位,那 Node.js 就是第二個引爆點。隨著 Node.js 的快速發(fā)展,JavaScript 真正變成了一種通用的腳本語言,在下面的各種領(lǐng)域大放異彩。
四、 CLI 應用的軍火庫 NPM
如果說 Node.js 是廚房,NPM (Node Package Manager) 則提供了豐富的各式食材,并在很短的時間成為了開發(fā)界最大的包管理平臺。
在 NPM 上涌現(xiàn)出涵蓋網(wǎng)絡(luò)服務,數(shù)學,文檔處理,數(shù)據(jù)庫,開發(fā)工具等幾乎涵蓋所有領(lǐng)域的各類應用??梢栽L問 Awesome Node.js 了解其強大之處。
?
五、奮戰(zhàn)在移動端的 Hybird App
隨著 iOS 和 Android 的崛起,只會 JavaScript 的前端工程師開始眼紅收入超越自己的 iOS 和 Android 工程師,于是他們聯(lián)合起來提出了 PhoneGap,一個將 HTML5 和 JavaScript 封裝成移動應用的平臺。希望借此實現(xiàn)開發(fā)一份代碼,適配兩個平臺,賺三份工資的偉大理想。然而事與愿違, PhoneGap 生成的跨平臺應用(Hybird App)由于性能、兼容性、對 native 功能支持不理想等問題,并沒有被特別廣泛的使用,也沒有實現(xiàn)前端工程師的漲薪夢想。
基于網(wǎng)頁的 Hybrid App 也有一些獨特優(yōu)勢,比如可以遠程推送更新,無需像原生程序一樣需要編譯和發(fā)布新版本,這個特性尤其適合電商或內(nèi)容為主的應用。而且畢竟開發(fā)容易,可用于早期試錯和產(chǎn)品方向驗證。真正要追求性能和品質(zhì),還是要用原生代碼(native code)來改寫。所以很多應用采用了原生和網(wǎng)頁混合模式,交互操作多,有性能要求,內(nèi)容相對固定的部分用原生實現(xiàn);重內(nèi)容重排版需要經(jīng)常更新的部分用網(wǎng)頁實現(xiàn),最大化兩者的優(yōu)勢。
六、桌面端即是網(wǎng)頁的 Electron
2014年,Atom 項目啟動。隨著 Atom 的演化,團隊獨立出用于支撐 Atom 跨平臺的底層架構(gòu) Atom Shell,后更名為 Electron。包括著名的 Slack,Visual Studio Code 的客戶端都是基于 Electron 構(gòu)建的。
Electron 底層是基于 Chromium 和 Node.js。Electron 做了幾件事:
1. 創(chuàng)建主進程(main process),主進程將為每個界面創(chuàng)建單獨的渲染進程(renderer process)。
2. 每個界面本質(zhì)上就是一個網(wǎng)頁,渲染進程將網(wǎng)頁代碼在 Chromium 中渲染成網(wǎng)頁顯示出來。
3. Electron 實現(xiàn)了各平臺的特殊功能(比如菜單,Dock),并為這些網(wǎng)頁界面提供原生功能的調(diào)用接口,使得應用可以實現(xiàn)原生應用才能做的很多功能,并可以使用 Node.js 的全部模塊(Module)。
如果你需要實現(xiàn)一些 Electron 或 Node.js 不支持的功能,可以自己用 C++ 寫 Module 來實現(xiàn)。
由于 Electron ?內(nèi)建了特定版本的 Chromium,所以優(yōu)勢是網(wǎng)頁設(shè)計時不用考慮兼容性(謝天謝地),劣勢是會導致 Electron 什么也不做的情況下,應用體積也在 100 MB 左右,打包壓縮后大約 30-50 MB。Electron 也繼承了 Chromium 的特點,啟動慢,利用資源(內(nèi)存占用)換性能(流暢度)。
NW.js 也是類似的框架,他采用了 Node.js + Webkit 組合。兩者各有優(yōu)劣,NW.js 跟 Electron 的完整功能對比。國內(nèi)釘釘客戶端是基于 NW.js 做的。網(wǎng)易自己造了兩個輪子貌似已經(jīng)停更的 Hex 和 NEJ,網(wǎng)易云音樂客戶端是基于 NEJ 的。
Electron 類的網(wǎng)頁封裝成客戶端另一個問題是源代碼很難被保護。由于 JavaScript 是解釋型語言,無法通過編譯來保護代碼,自身也沒有很好的代碼混淆方式,所以并不適用于需要版權(quán)保護或者純靠客戶端功能收費的應用。Electron 上曾有 issus 討論源代碼保護的話題,但官方的態(tài)度是 wontfix 。如果需要寫一些需要保密的代碼,可以考慮用 C++ 寫 Node module 來解決。
結(jié)語、Learn once, write everywhere
這幾天查資料時而感覺 JavaScript 威力無窮,時而又覺得它在哪個平臺都是點到為止,像玩具和試驗,距離工程性還有距離。JavaScript 有種鳩摩智用吐蕃內(nèi)功練少林七十二絕學的意味。
或許照這個發(fā)展勢頭,以后世上只有兩種工程師, JavaScript 工程師和其他工程師……
這幾天調(diào)研有些倉促,如果寫的不對的地方也請斧正。
原文發(fā)自我的微信公眾賬號:liujiong-blog