您聽說過 Node.js,但不確定它是什麼,也不知道它如何融入您的開發流程?或者,您可能聽說過人們對 Node 的讚揚,現在想知道是否需要學習它。也許您熟悉其他後端技術,並想了解 Node 的不同之處。如果這聽起來像您,請繼續閱讀。在本文中,我將以初學者友好的高級視角來探討 Node.js 及其主要範例。我將研究 Node 的主要用例,以及 Node 當前的格局,並在此過程中為您提供各種出發點(以供進一步閱讀)。 請注意,在整篇文章中,我將交替使用“Node”和“Node.js”。
關鍵要點
什麼是 Node.js?
網上有很多定義。讓我們來看幾個比較流行的定義。這是項目主頁上的說法:> Node.js® 是一個基於 Chrome 的 V8 JavaScript 引擎構建的 JavaScript 運行時。
而 Stack Overflow 提供的是:> Node.js 是一個基於事件、非阻塞、異步 I/O 運行時,它使用 Google 的 V8 JavaScript 引擎和 libuv 庫。
嗯,“基於事件”、“非阻塞”、“異步 I/O”——一下子很難消化這麼多信息。因此,讓我們從不同的角度來處理這個問題,首先關注這兩個描述中提到的另一個細節——V8 JavaScript 引擎。
V8 引擎是在 Google Chrome 和其他基於 Chromium 的 Web 瀏覽器(包括 Brave、Opera 和 Vivaldi)中運行的開源 JavaScript 引擎。它的設計考慮到了性能,負責將 JavaScript 直接編譯成計算機可以執行的原生機器代碼。但是,當我們說 Node 是基於 V8 引擎構建時,我們並不是說 Node 程序是在瀏覽器中執行的。它們不是。相反,Node 的創建者(Ryan Dahl)採用了 V8 引擎,並通過各種功能對其進行了增強,例如文件系統 API、HTTP 庫和許多與操作系統相關的實用程序方法。這意味著 Node.js 是一個程序,我們可以用它在我們的計算機上執行 JavaScript。換句話說,它是一個 JavaScript 運行時。
如何安裝 Node.js?
在本節中,我們將安裝 Node 並編寫幾個簡單的程序。我們還將了解 npm,這是一個與 Node 捆綁在一起的包管理器。
許多網站會建議您訪問 Node 官方下載頁面並獲取適合您系統的 Node 二進製文件。雖然這有效,但我建議您改用版本管理器。這是一個程序,允許您安裝多個版本的 Node 並隨意在它們之間切換。使用版本管理器有很多優點。例如,它可以消除使用 Node 和 npm 時可能出現的權限問題,並允許您為每個項目設置 Node 版本。如果您想使用版本管理器,請參考我們的快速提示:使用 nvm 安裝多個版本的 Node.js。否則,從上面的鏈接獲取適合您系統的正確二進製文件並安裝它們。
您可以通過打開終端並鍵入 node -v 來檢查 Node 是否已安裝在您的系統上。如果一切順利,您應該看到類似 v12.14.1 的內容顯示。這是撰寫本文時的當前 LTS 版本。接下來,創建一個名為 hello.js 的新文件並複制以下代碼:
console.log("Hello, World!");
這使用 Node 的內置 console 模塊在終端窗口中顯示消息。要運行此示例,請輸入以下命令:
node hello.js
如果 Node.js 配置正確,“Hello, World!” 將顯示出來。
如本兼容性表所示,Node 對 ECMAScript 2015 (ES6) 及更高版本提供了極好的支持。由於您只針對一個運行時(V8 引擎的特定版本),這意味著您可以使用最新和最現代的語法編寫 JavaScript。這也意味著您通常不必擔心兼容性問題——如果您編寫的是將在不同瀏覽器中運行的 JavaScript,則會遇到這種情況。為了說明這一點,這裡有一個第二個程序,它使用了幾個現代 JavaScript 功能,例如標記模板字面量、對象解構和 Array.prototype.flatMap():
console.log("Hello, World!");
將此代碼保存到名為 index.js 的文件中,並使用命令 node index.js 從終端運行它。您應該看到 Brendan Eich is the creator of JavaScript! ┌(˘⌣˘)ʃ 輸出到終端。
介紹 npm,JavaScript 包管理器
如前所述,Node 附帶一個名為 npm 的包管理器。要檢查您的系統上安裝了哪個版本,請鍵入 npm -v。除了是 JavaScript 的包管理器之外,npm 還是全球最大的軟件註冊中心。有超過 1,000,000 個 JavaScript 代碼包可供下載,每週下載量達數十億次。讓我們快速了解一下如何使用 npm 安裝包。
打開您的終端並鍵入以下內容:
node hello.js
這將在您的系統上全局安裝 jshint 包。我們可以用它來 lint 上一個示例中的 index.js 文件:
function upcase(strings, ...values) { return values.map(name => name[0].toUpperCase() + name.slice(1)) .join(' ') + strings[2]; } const person = { first: 'brendan', last: 'eich', age: 56, position: 'CEO of Brave Software', }; const { first, last } = person; const emoticon = [ ['┌', '('], ['˘', '⌣'], ['˘', ')', 'ʃ'] ]; console.log( upcase`${first} ${last} is the creator of JavaScript! ` + emoticon.flat().join('') );
您現在應該會看到許多與 ES6 相關的錯誤。如果您想修復它們,請將 /* jshint esversion: 6 */ 添加到 index.js 文件的頂部,重新運行該命令,並且 lint 應該通過。如果您想複習一下 lint,請參閱 JavaScript Lint 工具的比較。
我們還可以將包本地安裝到項目中,而不是全局安裝到我們的系統中。創建一個測試文件夾,並在該目錄中打開一個終端。接下來鍵入以下內容:
npm install -g jshint
這將在同一文件夾中創建並自動填充 package.json 文件。接下來,使用 npm 安裝 lodash 包並將其保存為項目依賴項:
jshint index.js
創建一個名為 test.js 的文件並添加以下內容:
npm init -y
最後,使用 node test.js 運行腳本。您應該看到 [ 1, 2, 3 ] 輸出到終端。
如果您查看測試目錄的內容,您會注意到一個名為 node_modules 的文件夾。這是 npm 保存 lodash 和 lodash 依賴的任何庫的地方。 node_modules 文件夾不應簽入版本控制,實際上,可以通過在項目的根目錄中運行 npm install 隨時重新創建它。如果您打開 package.json 文件,您會看到 lodash 在 dependencies 字段下列出。通過這種方式指定項目的依賴項,您可以允許任何地方的任何開發人員克隆您的項目並使用 npm 安裝運行所需的所有包。如果您想了解更多關於 npm 的信息,請務必閱讀我們的文章 npm 初學者指南——Node 包管理器。
Node.js 用於什麼?
既然我們已經知道Node 和npm 是什麼以及如何安裝它們,我們可以將注意力轉向它們的常見用途之一:安裝(通過npm)和運行(通過Node)各種構建工具——旨在自動化現代JavaScript 應用程序的開發過程。這些構建工具種類繁多,在現代 JavaScript 環境中,您如果不遇到它們就無法走得太遠。它們可以用於任何事情,從將您的 JavaScript 文件和依賴項捆綁到靜態資產,到運行測試,或自動代碼 lint 和样式檢查。我們在 SitePoint 上有很多文章介紹構建工具。以下是我最喜歡的一些文章:
如果您想開始使用任何現代 JavaScript 框架(例如 React 或 Angular)開發應用程序,則需要具備 Node 和 npm(或 Yarn)的工作知識。這並不是因為您需要 Node 後端來運行這些框架。您不需要。而是因為這些框架(以及許多相關的包)都可通過 npm 獲得,並且依賴於 Node 來創建一個合理的開發環境,以便它們可以在其中運行。如果您有興趣了解 Node 在現代 JavaScript 應用程序中扮演什麼角色,請閱讀現代 JavaScript 應用程序的剖析。
Node.js 允許我們在服務器上運行 JavaScript
接下來,我們來看 Node.js 最大的用例之一——在服務器上運行 JavaScript。這不是一個新概念,早在 1994 年 Netscape 就首次嘗試過。然而,Node.js 是第一個獲得任何實際吸引力的實現,與傳統語言相比,它提供了一些獨特的優勢。 Node 現在在許多知名公司的技術棧中扮演著關鍵角色。讓我們來看看這些好處是什麼。
非常簡單地說,當您連接到傳統服務器(例如 Apache)時,它將生成一個新線程來處理請求。在 PHP 或 Ruby 等語言中,任何後續的 I/O 操作(例如,與數據庫交互)都會阻塞代碼的執行,直到操作完成。也就是說,服務器必須等待數據庫查找完成才能繼續處理結果。如果在此期間有新的請求進來,服務器將生成新的線程來處理它們。這可能效率低下,因為大量線程會導致系統變得遲緩——最壞的情況下,會導致網站宕機。支持更多連接最常見的方法是添加更多服務器。
然而,Node.js 是單線程的。它也是事件驅動的,這意味著 Node 中發生的一切都是對事件的反應。例如,當一個新的請求進來(一種事件)時,服務器將開始處理它。如果它隨後遇到阻塞 I/O 操作,它不會等待此操作完成,而是在繼續處理下一個事件之前註冊一個回調。當 I/O 操作完成(另一種事件)時,服務器將執行回調並繼續處理原始請求。在後台,Node 使用 libuv 庫來實現這種異步(即非阻塞)行為。 Node 的執行模型使服務器幾乎沒有開銷,因此它能夠處理大量並發連接。擴展 Node 應用程序的傳統方法是克隆它,並讓克隆的實例共享工作負載。 Node.js 甚至有一個內置模塊來幫助您在單個服務器上實現克隆策略。下圖描述了 Node 的執行模型:
來源:Christian Maderazo 教授和 James Santos 的 Node.js 簡介
或者,如果您喜歡視頻,請查看這個精彩的演講:事件循環到底是什麼?它不是 Node 特有的,但它很好地解釋了這個概念。
Node 在單個線程中運行這一事實確實帶來了一些限制。例如,應避免阻塞 I/O 調用,應將 CPU 密集型操作交給工作線程,並且應始終正確處理錯誤,以免使整個進程崩潰。一些開發人員也不喜歡 JavaScript 強加的基於回調的編碼風格(以至於甚至有一個網站專門介紹編寫異步 JavaScript 的恐怖之處)。但是,隨著原生 Promise 的到來,緊隨其後的是 async await,現代 JavaScript 中的流程控制比以往任何時候都更容易。
讓我們快速瀏覽一下“Hello, World!” HTTP 服務器示例:
console.log("Hello, World!");
要運行此代碼,請將代碼複製到名為 hello-world-server.js 的文件中,並使用 node hello-world-server.js 運行它。打開瀏覽器並導航到 https://www.php.cn/link/4a914e5c38172ae9b61780ffbd0b2f90 以查看瀏覽器中顯示的“Hello, World!”。現在讓我們來看看代碼。我們首先需要 Node 的原生 HTTP 模塊。然後,我們使用它的 createServer 方法創建一個新的 Web 服務器對象,我們將一個匿名函數傳遞給它。此函數將為與服務器建立的每個新連接調用。匿名函數使用兩個參數(request 和 response)調用。這些包含來自用戶的請求和響應,我們使用它們來發送 200 HTTP 狀態代碼以及我們的“Hello World!”消息。最後,我們告訴服務器監聽端口 3000 上的傳入請求,並向終端輸出一條消息,讓我們知道它正在運行。顯然,在 Node 中創建甚至是一個簡單的服務器還有更多內容(例如,正確處理錯誤非常重要),因此如果您想了解更多信息,我建議您查看文檔或查閱我們的教程。
Node.js 適合哪種應用程序?
Node 特別適合構建需要某種形式的實時交互或協作的應用程序——例如,聊天網站或 CodeShare 等應用程序,您可以在其中觀看其他人實時編輯文檔。它也適合構建 API,在 API 中您處理許多 I/O 驅動的請求(例如需要對數據庫執行操作的請求),或者涉及數據流的網站,因為 Node 使您能夠在文件仍在上傳時處理文件。如果 Node 的這個實時方面是您想了解更多內容的內容,請查看我們關於構建實時聊天應用程序的教程。然而,並非每個人都會構建下一個 Trello 或下一個 Google Docs,實際上,您沒有理由不能使用 Node 來構建一個簡單的 CRUD 應用程序。但是,如果您遵循此路線,您很快就會發現 Node 非常基礎,並且構建和組織應用程序的方式很大程度上取決於您自己。您可以使用各種框架來減少樣板代碼,其中 Express 已確立了自己作為領先者的地位。然而,即使是 Express 這樣的解決方案也是最小的,這意味著如果您想做一些稍微不同尋常的事情,您需要從 npm 中引入其他模塊。這與 Rails 或 Laravel 等框架形成鮮明對比,後者開箱即用地提供了許多功能。如果您想了解如何構建一個基本的、更傳統的應用程序,請查看我們的教程如何構建和組織 Node.js MVC 應用程序。
Node.js 的優勢是什麼?
除了速度和可擴展性之外,在 Web 服務器以及瀏覽器中使用 JavaScript 的一個經常被提及的優勢是,您的大腦不再需要切換模式。您可以使用同一種語言完成所有工作,作為開發人員,這會讓您更高效(希望也更快樂)。例如,您可以輕鬆地在服務器和客戶端之間共享代碼。 Node 的另一個重要優勢是它使用 JSON。 JSON 可能是 Web 上最重要的數據交換格式,也是與對像數據庫(例如 MongoDB)交互的通用語言。 JSON 非常適合 JavaScript 程序使用,這意味著當您使用 Node 時,數據可以在層之間流暢地流動,而無需重新格式化。您可以從瀏覽器到服務器到數據庫都使用一種語法。最後,JavaScript 無處不在:我們大多數人都熟悉 JavaScript,或者在某些時候使用過它。這意味著過渡到 Node 開發可能比過渡到其他服務器端語言更容易。引用 Craig Buckler 在他的 Node 與 PHP 對決中的話,JavaScript 可能是世界上最容易被誤解的語言——但是,一旦概念點擊,它會讓其他語言顯得笨拙。
Node 的其他用途
它並不止於服務器。 Node.js 還有許多其他令人興奮和多樣的用途!例如,它可以用作腳本語言來自動執行您 PC 上重複性或容易出錯的任務。它還可以用來編寫您自己的命令行工具,例如這個 Yeoman 風格的生成器來搭建新的項目。 Node.js 還可以用來構建跨平台桌面應用程序,甚至可以用來創建您自己的機器人。還有什麼不喜歡的呢?
結論
JavaScript 無處不在,Node 也是一個龐大而廣泛的主題。儘管如此,我希望在本文中,我已經為您提供了開頭承諾的關於 Node.js 及其主要範例的初學者友好的高級視角。我還希望,當您重新閱讀我們之前看到的定義時,事情會更有意義。
Node.js 是一個基於事件、非阻塞、異步 I/O 運行時,它使用 Google 的 V8 JavaScript 引擎和 libuv 庫。
如果您有任何問題或意見,請隨時在 Twitter 上聯繫我。
關於 Node.js 的常見問題
JavaScript 是一種編程語言,主要用於客戶端的 Web 開發。它是一種在瀏覽器中運行的語言。另一方面,Node.js 是一個運行時環境,允許 JavaScript 在服務器端運行。它基於 Chrome 的 V8 JavaScript 引擎構建。 Node.js 擴展了 JavaScript 的功能,使其能夠與 I/O API 交互、執行網絡功能和訪問數據庫,這些功能通常在基於瀏覽器的 JavaScript 中不可用。
由於其非阻塞、事件驅動的架構,Node.js 在服務器端編程中很流行。這意味著它可以同時處理多個客戶端請求,而無需等待網絡請求或數據庫操作等任務完成。這使得 Node.js 高效且適合實時應用程序,例如聊天應用程序、協作工具和遊戲服務器。
Node.js 使用其事件驅動、非阻塞 I/O 模型處理並發請求。當發出請求時,Node.js 執行操作,然後繼續執行下一個請求,而無需等待先前的操作完成。操作完成後,將觸發一個事件,並執行相應的回調函數。這允許 Node.js 使用單個服務器處理數千個並發連接。
雖然 Node.js 主要用於服務器端開發,但它也可以用於前端開發。 Node.js 提供了一些工具和框架,例如 Express.js 和 Socket.IO,可用於構建強大的前端應用程序。此外,Node.js 用於運行 Babel 和 Webpack 等構建工具,這些工具在現代前端開發中必不可少。
NPM 或 Node 包管理器是 Node.js 開發中必不可少的工具。它是一個包管理器,允許開發人員安裝、更新和管理 Node.js 應用程序所需的各種庫和依賴項。 NPM 提供了一個大型的開源包存儲庫,使開發人員更容易共享和重用代碼。
Node.js 與 PHP 和 Ruby on Rails 在幾個方面有所不同。與同步的 PHP 和 Ruby on Rails 不同,Node.js 是異步的和非阻塞的,這意味著它可以同時處理多個請求。這使得 Node.js 更高效且適合實時應用程序。此外,Node.js 使用 JavaScript,這是一種許多開發人員熟悉的語言,從而降低了學習曲線。
Node.js 功能多樣,可用於各種應用程序。它特別適合構建可擴展的網絡應用程序、實時應用程序(如聊天應用程序和遊戲服務器)、協作工具和 API 服務器。 Netflix、LinkedIn 和 Uber 等公司在其技術棧中使用 Node.js,因為它高效且快速。
雖然 Node.js 提供了許多好處,但它也面臨一些挑戰。其異步、非阻塞的特性可能使代碼難以理解和調試。此外,由於 Node.js 是單線程的,因此 CPU 密集型任務可能會阻塞整個服務器,從而影響性能。但是,可以通過良好的編碼實踐以及適當使用工具和庫來減輕這些挑戰。
Node.js 通過首個錯誤回調處理錯誤。這意味著傳遞給回調函數的第一個參數是一個錯誤對象。如果在執行異步操作期間發生錯誤,它將作為第一個參數傳遞給回調函數。如果沒有發生錯誤,則此參數將為 null。
是的,Node.js 可以與各種類型的數據庫交互,包括 SQL 和 NoSQL 數據庫。有幾個庫和 ORM(對象關係映射)可用,例如用於 SQL 數據庫的 Sequelize 和用於 MongoDB 的 Mongoose,它們使在 Node.js 應用程序中與數據庫交互更容易。
所有圖片格式均保持為 .jpg
或 .webp
。
以上是node.js簡介的詳細內容。更多資訊請關注PHP中文網其他相關文章!