Node.js是什麼?能做什麼?終於有人講明白了

導讀:本文我們來認識一下Node.js,瞭解它能幫助我們完成哪些工作。
作者:史文強
來源:大資料DT(ID:hzdashuju)
在JavaScript語言努力擺脫“玩具語言”這個標籤的進化歷程中,Node.js絕對能記下濃墨重彩的一筆。Node.js並不是一個用於實現具體功能的第三方工具庫,而是JavaScript程式的執行環境。
在Node.js出現之前,使用JavaScript語言編寫的指令碼需要在網頁中被<script>標籤引用後才能執行,這就使得前端開發人員編寫的程式無論怎麼看都像是介面的一種附屬品。而Node.js的出現打破了這個枷鎖,它提供的執行時能夠讓JavaScript程式在桌面、命令列終端、手機、平板電腦甚至嵌入式系統上執行,這不僅極大地豐富了JavaScript的應用場景,也為後來的前端工程化發展和中間層架構模型的興起奠定了基礎。
十多年的技術沉澱和演進使得Node.js早已經不再是一項擴充套件閱讀範疇的新興技術,而是前端開發人員必須掌握的技能,那句“不懂Node的前端是不完整的”也早已不再是一句玩笑話。
Node.js的出現使得前端開發人員可以不必切換語言就能完成客戶端和服務端的開發,瞭解它的人往往對它愛不釋手,而不瞭解它的人則常會把它看作前端工程師自娛自樂的玩具,認為Node.js能做到的事情Java都能做而且更加成熟。那麼Node.js到底能做什麼,又適合做什麼呢?
01 Node.js是什麼
Node.js是一個基於Chrome V8引擎的JavaScript執行環境。Node.js使用了一個事件驅動的、非阻塞式I/O的模型,輕量又高效,它的底層是用C/C++編寫的。這是Node.js的官方描述,對前端開發人員來說,想要搞清楚其中所包含的“引擎”“執行環境”“事件驅動”以及“非阻塞I/O模型”到底是什麼意思,並不是一件容易的事情。
那麼Node.js到底是什麼?我們先用一個類比的示例來進行解釋。比如,有人向你傳送了一個副檔名為docx的文件,你想要檢視其中的內容,於是開啟記事本,把該文件拖到記事本的窗口裡,然後就看到了一大堆亂碼。這是因為記事本程式並不能識別這種格式的文件,你需要先安裝Microsoft Office 2007以上版本的軟體,然後用Word程式開啟,這樣才能看到正確解碼的內容。
如果把示例中的docx檔案看作程式,那麼Word就是它的執行環境,這就像JavaScript程式與瀏覽器的關係一樣。如果你瞭解過現代瀏覽器的結構,就會知道其中包含了JavaScript引擎。
以前,想要檢視docx檔案的內容,幾乎只能依賴於Microsoft Office,後來金山公司也推出了辦公軟體工具WPS Office,它也能夠解釋和執行docx檔案,於是docx檔案就有了多個可執行環境,而Node.js對於JavaScript語言的意義也是如此。
為了更加直觀地理解執行時的概念,你可以嘗試一個有趣的實驗,自己創造一種簡單的程式語言,規定一些簡易的語法,然後使用JavaScript來編寫能夠解釋這些語法的程式碼。
例如,用自創的語言編寫一些簡單的程式,最後透過Node.js執行JavaScript程式,並在程式中用Node.js提供的檔案讀寫介面(File API)讀入你用自創的程式語言編寫的程式,看看它能否被正確地解釋和執行。待你瞭解了JavaScript是如何完成對自創程式語言的解釋和執行的,自然就能明白在Node.js執行環境中,C/C++對JavaScript指令碼做了什麼事情。
當然,真實的程式碼解釋執行過程要複雜得多,很多關鍵的思想和技術也被應用在前端框架的設計中,這些可以在今後的學習中慢慢消化。
相較於技術上的亮點,Node.js設計者的開發思想或許更值得學習,這一點正是大多數初級開發者所缺少的。Node.js的開發初衷是更方便地實現一個高效能的Web伺服器,但當它最終問世時,並沒有宣稱自己是“實現高效能Web伺服器的技術”,而是為開發人員提供了一個工具,這個工具的能力之一是實現高效能的Web伺服器。
這種思想差距在初級和高階開發人員之間表現得尤為明顯:初級開發人員往往會針對具體的業務需求採用面向過程的風格進行開發,這使得他們編寫的程式幾乎無法靈活應對任何需求變更;而有經驗的開發人員面對需求時,通常會先設計一個類,或者抽象一個與業務邏輯無關的工具方法,然後在自己的程式中呼叫這個方法。
要想成為優秀的程式設計師,就要不斷地培養自己設計程式的能力,而不是僅僅完成語言層面的翻譯工作。
02 Node.js能做什麼
在Node.js的諸多功能中,與前端開發人員關係最緊密的就是建立Web伺服器和本地檔案的讀寫能力。
1. 建立高效能Web伺服器
許多Node.js的初學者應該都見過那段只用了不到10行程式碼就建立了一個Web伺服器的經典示例。儘管對於前端開發人員而言,他們依然需要學習基本的Web伺服器知識,才能更加得心應手地進行服務端開發,但與配置Apache或Nginx來實現同樣的功能相比,這樣的學習成本已經非常低了,畢竟前端開發人員可以使用自己最熟悉的JavaScript語言來構建應用。
另一方面,在Node.js中,程式碼可以與各類資料庫進行互動,這就意味著前端工程師可以直接使用JavaScript語言編寫與資料庫進行互動的程式碼(儘管在大型應用中並不推薦這樣做),且編寫業務邏輯程式碼時,Node.js與其他後端語言沒有明顯的差別,因此前端開發人員不用切換開發語言就可以掌握全棧開發的技能。
由於Node.js底層使用的是非同步非阻塞的I/O機制,因此它更適合於I/O密集、少量業務邏輯和計算消耗的場景。儘管解釋型指令碼語言本身並不適合執行計算型任務,但Node.js底層是由C/C++程式碼編寫的,並且提供了JavaScript程式碼層與C/C++程式碼互動的介面,面對計算密集型任務時,Node.js只需要作為啟動指令碼呼叫底層C/C++程式來完成計算密集型任務就可以了。
服務端執行的任務大體可分為讀寫密集型任務計算密集型任務。對於讀寫密集型任務而言,CPU更多的時間是在等待磁碟讀寫,使用率並不高,在Web伺服器上進行的網路通訊、資訊傳輸和磁碟讀寫等都屬於讀寫操作,它對磁碟的響應速度和傳輸效率有著更高的需求。
相較而言,計算密集型任務對CPU的運算能力要求更高,但對磁碟讀寫造成的效能負擔很小,計算過程中通常也不需要與I/O介面進行互動,可直接、高效地在記憶體中執行,這類任務的計算過程通常比較複雜,例如需要實現某些加密演算法或者矩陣計算等。
大型架構的後端技術選型需要考慮的因素更為複雜,Node.js設計之初並沒有準備承擔這項任務,就連Node.js之父Ryan Dhal自己也說,在面對大型服務端應用開發時,Node.js的開發體驗不如Go語言。
但是,全世界目前有600多種程式語言,沒有任何一種語言能夠解決所有問題,語言只是承載和傳遞程式設計思想的媒介,如何為目標場景選擇一項合適的技術,或許是開發人員更應該關注的問題。
當你在前端領域有一定的積累時,很多前輩都會推薦你繼續學習Java或C++等更為完備也更為複雜的語言,這樣做的目的並不僅僅是擴充套件能力邊界,更多的是希望你能夠跳出一種程式語言的束縛,學習和體會程式語言背後的思想。
2. 本地檔案的讀寫功能
檔案讀寫功能的底層所要解決的問題其實有很多。如果檔案裡的內容比較多,讀入記憶體的過程比較耗時,應該怎麼處理呢?是等待讀入操作完成還是先去執行其他任務?如果客戶端請求的資源是一部高畫質電影,檔案比程式可用的總記憶體還大,那麼該檔案是否就一定無法讀取了呢?
Node.js的fs模組幾乎為每個檔案操作介面都提供了同步和非同步兩種方法,同時也支援以流的方式對讀寫過程實現更細粒度的控制,甚至還可以監測指定檔案或資料夾的變動。檔案可讀寫意味著開發人員可以透過程式分析另一個程式中檔案的內容,並對其進行檢查和糾錯,甚至可將其編譯成另一種語言,這便是前端工程化的能力基石。
03 招黑的JavaScript全棧工程師
Node.js憑藉建立高效能Web伺服器以及與資料庫通訊的能力,為前端開發人員提供了服務端開發的機會。早在幾年之前,開發人員就可以使用MEAN(MongoDB + Express + Angular.js + Node.js)這種純JavaScript技術棧完成閉環的業務邏輯開發,很多前端工程師也因此自詡為全棧工程師。
不可否認當年這樣的技術棧確實可以使許多中小型團隊以更少的人力和時間就把產品從創意階段推進到線上,但這也使得JavaScript開發人員成為業內最招黑的全棧工程師,因為業務邏輯的實現並不足以撐起全棧工程師進行後端開發。
在企業級開發中,後端開發仍然以Java工程師為主力軍。
由於Java本身具有強型別和完整的面向物件的特性,因此後端工程師的編碼質量和程式設計意識整體要高於前端工程師,再加上與Java開發體驗非常相似的Angular技術棧的支援(Angular本身就是一項由Google的Java工程師開發和維護的技術),後端工程師很容易就能編寫出規範性和可維護性都不輸於前端開發人員的程式碼,這大大提升了Java全棧工程師的競爭力。
如果不是工程化配置和CSS實戰經驗形成的門檻,前端工程師在面對後端全棧工程師時很難體現其自身價值。然而,前端開發出身的工程師在使用Node.js技術棧進行服務端開發時卻沒有那麼順利,最流行的Express和Koa框架,僅僅提供了框架和基本中介軟體,要想實現更多的功能,還需要引入或者自行開發大量中介軟體。
這時開發人員之間的差別就會表現得非常明顯,即使完全不懂Node.js,後端開發人員也很清楚自己應該尋找具備日誌記錄、錯誤追蹤、會話管理、安全校驗、效能監控、物件關係對映(ORM)、資料庫連線等功能的模組或中介軟體,而普通的前端開發人員卻除了業務邏輯的增刪改查外,往往連使用“try…catch…”語句捕獲執行時錯誤的意識都沒有。
前端工程師很容易只考慮業務邏輯一切正常的情況,只要主流程能夠正常執行,就覺得萬事大吉了,然而在真實的開發過程中,往往是那些沒有覆蓋到的邊界情況需要花費更多的精力。
把後端開發等同於編寫業務邏輯程式碼,就好像把前端開發等同於編寫靜態頁面程式碼一樣。如果真的想成為全棧工程師,需要用一顆謙虛求知的心,踏踏實實地去學習那些陌生的知識,學習的過程可能充滿艱辛,但你一定會受益於所學的結果。
關於作者:史文強,前端資深技術專家,現任字節跳動幸福裡團隊前端工程師、西安交通大學航天學院特聘軟體工程師,華為云云享專家,曾受Google GDG(Google開發者社群)邀請進行技術分享。擁有豐富的實戰經驗,擅長大型前端系統架構設計、效能最佳化及工程化體系建設。
本文摘編自前端跨界開發指南:JavaScript工具庫原理解析與實戰》,經出版方授權釋出。(ISBN:978-7-111-70804-9

延伸閱讀《

前端跨界開發指南

點選上圖瞭解及購買
轉載請聯絡微信:DoctorData
推薦語:本書是字節跳動資深前端工程師嘔心瀝血之作,也是目前市場上少有的從原理到實戰深度剖析JavaScript生態中經典工具庫的技術圖書。
刷刷影片👇
更多精彩👇
在公眾號對話方塊輸入以下關鍵詞
檢視更多優質內容!
讀書 | 書單 | 乾貨|講明白|神操作 | 手把手
大資料 | 雲計算 | 資料庫 | Python | 爬蟲 | 視覺化
AI | 人工智慧 | 機器學習 | 深度學習 | NLP
5G|中臺 | 使用者畫像數學 | 演算法 數字孿生
據統計,99%的大咖都關注了這個公眾號
👇

相關文章