[Node.JS] 建立伺服器、掌握基本知識
前言
本系列文章記錄了如何用最基礎的方式建立 Node.js API 服務,目的在了解基本運作原理,實務上會運用其他框架、插件和中介軟體(Middleware)來快速完成環境建置。
💎 基本技能 - 模組引用
在 Node.js 中會使用 JavaScript 的模組方法來載入各種功能,這個段落會先介紹如何操作,如果已經熟悉可以跳過,進入下個段落。
範例情境:
- 主要檔案:a.js
- 模組-寫法1:b.js
- 模組-寫法2:c.js
a.js
- 使用 require 來引入其他資源
1 | // 自己的變數 |
b.js
- 使用 module.exports 設定被引用時提供的資料
1 | // 方法1- 直接設定要輸出的資料,多個資料時通常用物件格式來存放 |
c.js
- 使用 exports.屬性名稱 設定被引用時提供的資料
1 | // 方法2- 新增屬性的方式逐一增加輸出的資料 |
💎 創建本地伺服器 - createServer
學會模組引用的操作後,就可以試著撰寫第一個 js 檔案,讓 Node.js 建立一個伺服器服務:以下開發環境都使用 VS Code
- 建立伺服器 js 檔 (檔名自定)
下面這段程式碼是 node.js 官方範例
1 | // 引用 http 模組 |
- 啟動伺服器
開啟終端機(熱鍵為 Ctrl +`
),使用 Node.js 執行撰寫好的檔案,如果沒有跳出錯誤訊息就表示本地伺服器成功運行了。
1 | ** 請先將路徑切換到 js 存放的位置,檔案名稱修改為自己設定的名稱 ** |
關閉伺服器
伺服器執行的狀態下,在終端機視窗內按下Ctrl+C
就可以終止。連線測試
伺服器正常運作後可以開啟瀏覽器,輸入網址http://127.0.0.1:8000
,沒有問題的話就會顯示Hello
,這段網址中的 127.0.0.1 表示這部電腦的本地位置,冒號加上數字 8000 就可以指定使用前面步驟設定的 port 來連線。修改測試
試著修改 Content-Type 或 res.write 的內容,讓網頁顯示不一樣的資訊。
每次修改儲存後都需要重起 node,可以透過 npm 安裝nodemon
這個套件,就能在編輯檔案後自動重新載入伺服器。
1 | ** 安裝指令(建議全域安裝)** |
💎 程式碼說明
http
程式一開始引用了 node.js 中的 http
模組,並使用 createServer 方法來建立伺服器,模組的其他功能可以參考官方文件。
監聽連線請求
createServer 方法裡面傳入的函式像是 addEventListener 事件偵測,但監聽的行為
是有沒有連線請求
傳送到這台伺服器主機,這個監聽函式也可以使用變數獨立出來,增加一點可讀性,改寫後如下方程式碼:
1 | const http = require('http'); |
request
監聽函式帶有兩個參數,req
是 request(請求)的簡寫,當我們在瀏覽器網址列輸入網址送出連線,就會對該網址對應的伺服器主機發出請求,請求資訊會包含瀏覽器版本、需要的資源、請求的方式…等資訊,在 node.js 中可以透過 req 變數來查看詳細資訊。
- 觀察 req 的內容:
修改監聽函式 > 儲存檔案 > 重啟伺服器 > 瀏覽本地網址 > 在終端機查看 req 資訊
1 | const requestListener = (req, res) => { |
- req 的常用屬性:
req.url
:取得請求的資源路徑。一個網站會有好幾個檔案,透過這個屬性就可以取得請求的路徑,如果請求的網址後面沒有任何路徑,就會得到根目錄(/),通常會設置回應首頁頁面。req.method
:取得請求的方法。一般連線請求會使用 GET 方法,但是若有夾帶其他資訊時就會使用其他方法,各種方法可以參考 MDN 的說明。req.on("data", ...)
:取得請求夾帶的資料。當連線使用 POST、PATCH…等方法時通常回夾帶資料給伺服器處理,就會需要使用這個方法來接收。req.on("end", ...)
:資料接收完成後執行動作。網路封包傳遞會把資料切成片段,不會每次都一次傳完,所以在 on(data) 的階段無法確認收到的資料已經完成,要用這個方法才能確保資料接收完,再執行對應的程式碼。
response
res
是 response(回應)的簡寫,伺服器收到請求後,就會把設定好的資訊傳回用戶端,在簡易的範例中只會回應 Hello 的文字,可以撰寫程式碼結合 req.url 和 req.method 判斷來回應不同的內容。res.writeHead(status, header)
:回傳的表頭資訊。就像 req 一樣,res 不會只傳送單純的資料,需要包含各種資訊,status code 是狀態碼,200 就是成功,而 header 會告訴對方提供了哪些連線方法,這也是開發實務上容易採坑的地方,詳細的資訊都可以在 MDN 的 HTTP 主題中查看。Content-Type
:檔案格式。瀏覽器會依據這個屬性來決定怎麼讀取接收到的資料,常見的有 JSON(application/json)、HTML(text/html)、純文字(text/plain)…等。res.end()
:程式運作不像人類會自主開始或停止,所以需要執行一段程式碼明確的告知『我傳完了』,否則用瀏覽器連網頁後頁籤上方會一直出現轉圈圈的圖示(表示持續等待回應中)。
listen(port)
listen(8000)
:使用的通訊埠。HTTP 協定預設使用 80 port,1-1023 是系統保留,所以在自訂 port 的時候通常都是 X000 起跳。較安全的寫法
:寫好的網頁服務通常會放在各種雲端代管主機上,這些服務會由系統自動分配 port,如果程式碼寫死特定的 port,就無法跟雲端環境匹配,理所當然的就連不到,這時候可以利用環境變數 process.env.PORT 來取得執行環境的 port 號,就能動態調整讓服務正常運行,改寫如下:
1 | const PORT = process.env.PORT || XXXX; |
💎 探索 Req 與 Res - Postman
Postman 是一套網頁請求模擬工具,相較於用瀏覽器的 Dev 工具,Postman 專注於檢查 Request & Response,也能模擬各種請求行為(GET、POST、PATCH…等),有助於 API 的測試和 debug。
安裝 Postman
前往 Postman 官方下載,完成後執行安裝會跳轉至註冊會員網站,完成註冊後就可以使用了。
使用 Postman
進入操作介面後,一些設定或導覽可以都先略過,接著照以下步驟操作:
- 先點擊上方選單
HOME
- 點擊左側選單
Workspaces
- 選擇
My Workspace
- 點擊內容區塊上方分頁的
+
- 在網址列裡面輸入任一網址或是本地的網址(例如本篇文章練習的
http://127.0.0.1:8000
) - 送出後就能查看詳細資訊了
詳細教學也可以參考:
六角學院 - Postman 教學文章
💎 補充知識
Global 全域物件
每個執行中的軟體或是瀏覽器頁面就像是一個星球,每個星球就像是一個全域物件,囊括了星球上的所有東西,在網頁環境中的全域物件是 window
,而 Node.js 中是 global
。
雖然都是全域,除了名稱外也有些差異,假如在全域中引入兩個檔案(a.js 和 b.js),裡面都撰寫了 var a = 1
,這時網頁的 window.a
會得到 1
的結果,Node.js 的 global.a
則是 undefined
。
Node.js 中的每個模組都會是獨立的,不會互相干擾也不會變成全域變數(除非直接操作 global 物件),網頁中的 window 則可能被 var 變數影響(ES6 後建議全部改用 let 才不會污染全域)。
檔案路徑
一個專案中會有許多資料夾和檔案,要存取這些資源就需要知道檔案的路徑位置,才能順利找到檔案,Node.js 提供 path
模組,可以快速的分解、組合路徑。
- 全域變數:
__dirname
、__filename
可以取得當前的目錄和檔案名稱。
1 | // 目錄名稱 |
Path
:Node.js 的 path 模組提供許多方法來處理路徑。
1 | // 範例路徑 |
💎 結語
本篇的筆記記錄了如何使用 Node.js 本地建立伺服器、透過 Postman 檢查 Request & Response,接下來會記錄如何製作一個簡單的 todolist api。