封面圖片來源:Photo by Claudio Schwarz on Unsplash
本文整理自我初學 Node.js 時的筆記,用以向對 Node.js 這門語言有興趣的讀者簡明扼要的介紹 Node.js 是什麼,以及該如何學習這門語言。
1. 什麼是 Node.js?
Node.js 是 Ryan Dahl 在 2009 年為瞭解決 Web 伺服器高併發問題而開發的基於 Chrome V8 引擎的 JavaScript 執行時環境。
從這個定義中,可以看到 Node.js 的三個關鍵特徵:
- 目的是為瞭解決 Web 伺服器高併發問題;
- 根基是 Chrome V8 引擎;
- 本質是一個 JavaScript 執行時環境;
因此,要搞清楚什麼是 Node.js,首先就要搞清楚以上三個關鍵特徵。
1.1 Node.js 三個關鍵特徵
1.1.1 為瞭解決 Web 伺服器高併發問題
Ryan Dahl 在設計 Node 之前,一直致力於解決 Web 伺服器高併發引起的效能問題,根據工作經驗,他認為效能問題的瓶頸在於阻塞的 I/O 操作。恰逢 Chrome 推出了高效能的 V8 引擎,Ryan Dahl 認為 JavaScript 天然的非同步,事件委託機制以及 JavaScript 語言在服務端無歷史包袱的特性,非常適合透過非同步流程控制的方式提升大型分散式系統效能。於是,Node.js 應運而生。
儘管現在 Node.js 已經被應用於各種各樣的場景。但是我們始終應該認識到,理解 Node.js 的非同步流程控制原理才算是掌握了 Node.js 的核心。
1.1.2 Chrome V8 引擎
Chrome 核心基於 WebKit,分為以下兩個引擎:
- 渲染引擎:Web Core;
- JavaScript 解釋引擎:JavaScript Core;
而 Google 由於不滿意 JavaScript Core 的效能,於是自主研發了效能更好的 V8 引擎予以取代。
作為 JavaScript 的解釋引擎,V8 引擎的主要作用在於:
- 解釋與編譯 JavaScript;
- 堆管理;
- 處理記憶體垃圾回收;
- 處理記憶體分配;
- …
可以說,V8 引擎提供了一個高效能的 JavaScript 執行環境,因而 JavaScript 能夠有充足的底氣在各平臺(瀏覽器,服務端,桌面端)執行。
1.1.3 JavaScript 執行時環境
Node.js 既不是一門語言(JavaScript),也不是一個框架(React,Koa),而是一個 JavaScript 執行時環境。
那麼什麼是 JavaScript 執行時環境 呢?顧名思義,是一個可以執行 JavaScript 的環境。那麼這裡的環境是指什麼呢?主要包含以下兩個方面:
- 提供瞭解釋,編譯 JavaScript 的底層能力;
- 提供了一系列介面,使開發者可以透過 JavaScirpt 呼叫系統底層能力(例如網路,檔案讀寫等);
前者是由 Chrome V8 引擎提供的,而後者則是由一個底層由 C,C++ 編寫的高效能的事件驅動的非同步 I/O 庫 libuv
所提供。
1.2 libuv
libuv
是一個跨平臺的,事件驅動的非同步 I/O 庫,為 Node 提供了 CPU 和作業系統層面的功能。我們知道不同的作業系統排程硬體的方式不同,CPU 的指令集也各有差異。libuv
則抹平了這一差異,透過名為 Node Bindings
的模組,向使用者暴露了統一的系統操作介面。
因此現在我們可以說,Node 實際上由兩部分組成:Chrome V8 引擎以及 libuv
。這兩層隱藏在 Node Bindings
之下,而使用者面向 Node Bindings
進行程式設計。
至此,你應該理解了什麼是 Node.js。它是一個跨平臺的 JavaScript 可執行環境,在這個環境中,你可以使用 JavaScript 充分調動作業系統的能力,做你想做的任何事!
2. Node.js 的哲學
要充分的理解 Node.js,除了前文提到的非同步流程控制原理之外,我們還需要了解下 Node.js 從創始到發展所彰顯的設計哲學,這有利於我們更喜歡 Node.js 生態。
我認為 Node.js 有以下三大特點:
- 開放;
- 專注;
- 簡約;
讓我分別解釋。
2.1 開放
Node.js 在設計之初,就堅持將核心庫做的足夠小,以便讓充分發揮社群的創造性,讓所有搭建大型系統的構建都儘可能來源於社群,因此每個構件都可以快速試錯和迭代。不得不說,這種做法雖然有顯得有些偷懶,但是事實證明這種對社群的信賴,和開放的態度收穫了巨大的回報:Node.js 擁有了全世界最活躍也是最大的社群和包管理平臺 npm
。
2.2 專注
Node 社群的開發者始終保留著一個默契,將包的功能約束的足夠窄,最好一次只做好一件事,並對外暴露單一的介面。這樣包的開發,設計,測試就會變得更加簡單,包也就更加可靠。這種專注,也同時表現了開發者們的謙遜以及效率至上。
2.3 簡約
Node 包通常只暴露單一模組和介面,並繼承了 JavaScript 的簡約特點,使用簡單的資料結構。這使得 Node 包易於閱讀和理解。
3. 前端開發者如何學習 Node.js?
對於從未涉足過服務端開發的前端開發者而言,以下幾點是學習 Node 過程中必須補足的知識:
- 對 JavaScript 語言特性(特別是 ESNext),語法的深入理解;
- 資料庫知識與資料表設計能力;
- 系統架構能力;
而學習 Node.js 則可以分為兩個部分:
- 學習 Node.js 的核心庫的使用;
- 學習相關 Web 框架的使用;
在整個學習過程中,建議採用以下四步學習:
- 閱讀官方檔案;
- 撰寫 Demo 熟悉語法驗證思路;
- 在此過程中不斷地問自己問題,並深入調研得到答案;
- 透過對外輸出,分享所得加深自己的印象;
4. 小結
Node.js 在如今已經是每一位前端開發者必須掌握的技術,它透過 libuv 向前端開發者開放了作業系統層面的底層能力,讓開發者能夠全面使用計算機的算力和功能。並讓用一種語言解決 Web 應用開發的所有問題的想法成為可能。希望透過本文的介紹,您能夠對 Node.js 產生好奇,祝您在未來的探索旅途中,過得愉快。