[Node.js] Node.js Web 開發環境與語言架構指南

安裝 | NVM | NPM | Cluster

Intro

Node.js

Wiki

Node.js 採用 Google 開發的 V8 引擎執行 JavaScript 代碼,並完全承襲了 JavaScript Runtime 的事件驅動 (Event-driven)與單執行緒(Single-threaded)特性。透過其獨特的非阻塞 I/O (Non-blocking I/O)模型,Node.js 能在不增加額外執行緒負擔的情況下,高效處理高併發需求。

與其他語言最大的不同之處:

  • 傳統語言(如 PHP / Java 早期)使用阻塞式 I/O (Blocking I/O) 模型: 只有前一條命令執行完畢才會執行後面的命令
  • Node.js 使用非阻塞 I/O (Non-blocking I/O)模型: 任務可以發送後即繼續執行其他操作,多條命令可以同時被執行,通過 Callback 或 Promise 得知任務完成狀態

總之,Node.js 承襲了 JavaScript 著名的 Event loop 特性,在單一執行緒架構下可以輕易實現非阻塞 I/O 任務併發應用

為了方便理解,我們常說 Node.js 是「非阻塞 (Non-blocking)」,但更精確的技術定義是 「非同步 I/O (Asynchronous I/O)」。

  • Non-blocking 是指呼叫後不卡住。
  • Asynchronous 則是任務交給系統後「好了再叫我」。

Diagram


JavaScript Runtime:

JS Runtime
(Reference: Majedur Rahman)

  1. 初始同步代碼: 首先執行 Call Stack 中的同步任務(這被視為第一個 Macrotask)。

  2. 清空 Microtask: 當 Call Stack 清空後,Event Loop 會一次清空整個 Microtask Queue (如 Promise.then)。
    (取出一個 -> 放入 Call Stack 執行 -> 清空 Call Stack -> 再取下一個 Microtask)

  3. 執行單一 Task: 從 Task Queue 取出一個任務 (如 setTimeout) 放入 Call Stack 執行。

  4. 循環: 執行完該任務後,再次回到第 2 步 (檢查並清空 Microtask)。

在瀏覽器中,JavaScript 靠 Web APIs 處理非同步任務;而在 Node.js,這個角色由底層的 Libuv 實作接手 (Node APIs),轉化成相同的 Callback/Promise 開發體驗。

Promise.all() 的開發概念對應 Multithreading 中的 join(),但在實質上,它是透過 Event Loop 在單執行緒環境下達成的『併發 (Concurrency)』而非平行運算。


安裝 Node.js

Downloads - Node.js (官網提供不同版本與環境的指南)

檢查版本

$ node --version
v14.17.5

NVM (Node Version Manager)

NVM (Node Version Manager) 是一套開源的 Node.js 版本管理工具,方便使用者安裝、切換、管理指定的 Node.js 版本,適用於需要在同一台機器上同時支援多個 Node.js 版本的場景。

$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash
$ source ~/.bashrc
$ nvm --version

// List 遠端可安裝版本,安裝與選用
$ nvm ls-remote
$ nvm install 16
$ nvm ls  // 列出已安裝版本
$ nvm use 16
// 設定預設使用的 Node.js 版本
$ nvm alias default 16
$ nvm uninstall 16

NPM 套件管理器

Node.js 會一併安裝 NPM (Node Package Manager)

NPM JS

package.json - 放置於 Git 根目錄的 NPM 套件設定檔

Creating and publishing unscoped public packages - npm Docs

Namespace 規則: {package name} (與 Github 無關連)

專案內安裝套件

npm install {require package name}

常用指令

# 列出專案內清楚的已安裝套件
npm list --depth=0

# 列出全域已安裝套件
npm list --global

# 查看某package是否已安裝
npm list 

Quick Start

How do I start with Node.js after I installed it?

直接任一創建一個檔案app.js

console.log("Hello world");

接著使用node指令直譯程式:

$ node app.js
Hello world

常用函數

console.log()
return
process.exit()

Process / Environment Variable

Node JS Process

環境變數設定檔 .env for Process.env

利用建立.env檔案來設定環境變數並生效至runtime中的Process.env

記得.env.gitignore而勿上傳至Git repository

使用 dotenv 套件方式

dotenv 套件可以協助程式載入.env的變數至Process.env,安裝參考如下:

npm install dotenv --save

一般來說可以加入require('dotenv').config();至程式碼中以便啟動套件載入變數, 若不希望異動程式碼而想利用 Command 方式啟動,可以在指令中利用-r --require參數帶入以啟用:

node -r dotenv/config app.js

Web建置

快速建立HTTP Server

How do I create a HTTP server?

反向代理 Reverse Proxy

可以使用nginx做反向代理NodeJS App,如上述8080port本地web app,nginx反向代理設定範例如下:

server {
  listen 80;
  server_name _;
  location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
  }
}

Node Cluster - 多進程

Nodejs web server 同其語言性質一樣為 Single Thread 在處理 Requests (但為 Asynchronous I/O),可以透過 Node Cluster 模組在一台 Web server 上建立多個 worker,透過 IPC 與 父行程溝通,將工作分散至不同的 CPU 中處理。

Node Cluster


Concurrency - 並發/並行

Multi-threading

Multi-processing

在版本有支援 Worker threads 下應該很少情境會用上 Multi-processing。

Node.js | multi-process(多進程)


References

Leave a Reply

Your email address will not be published. Required fields are marked *