Node.js Express 初入門 – 上集

Express 可以說是 Node.js 中最流行的 Web 開發框架,不但有著簡潔靈活的特性、還有豐富的文件和完整的 API Reference,令開發者能快速地搭建一個完整功能的網站。

今天就讓我們來為介紹 Node.js Express 的常用功能,包括 Express 路由機制 (Routing)、Express 靜態網頁伺服器 (Static Web Server) 如何載入圖片、文本等靜態檔案到瀏覽器上。

 

■ 使用工具: 編輯器、Node.js 終端機與瀏覽器

在學習Express的過程中,我們主要會用到三項工具──編輯器 (Editor)、終端機 (Terminal, 或稱命令行Command Prompt) 與瀏覽器 (Browser)。

這邊我們使用的編輯器為 Atom,當然你也可以用 Vim、Sublime 等你喜歡的編輯器。

還沒有安裝 Node.js 的讀者可以去 Node.js 的官網下載,安裝完成後開啟 Node.js 的 Command Prompt,輸入 node –version (或node -v) 後確認安裝成功。

接下來,讓我們從頭開始創建一個 node 專案。在桌面建立一個叫做 express 的資料夾作為專案名稱(或任何你想要的名字)。建立完後在資料夾中運行 npm init、將該資料夾轉成一個 node 專案。

下列為輸入prompt的命令:

npm init 的動作會為此專案創建一些設定,並將這些資訊存在一個叫 package.json 的檔案中。

在 package.json 這個檔案中,使用者可以定義應用名稱 (name)、應用描述 (description)、關鍵字 (keywords)、版本號 (version)、應用配置 (config)、主頁 (homepage)、作者(author)、版本庫 (repository)、bug的提交地址 (bugs)、授權方式(licenses)… 等。

cd 到 Desktop 後,創建一個叫 express 的資料夾,再 cd 到 express 中輸入 npm init。接下來會有一些關於這個 node 專案的初始設定。

設定完成後輸入 ls 展開資料夾內所有的檔案 (Windows指令為 dir),可以發現 express 資料夾中出現 package.json 這個檔案了。

Windows Prompt使用者記得是用dir而不是用ls喔= =”

 

■ 安裝Express

太好了,接下來讓我們試試在express中initialize Express這個模組吧!

除了 install express 之外、還需在後面加上「–save」,這是什麼意思呢?在 npm 中,「Dependency」(依賴模組)是一個非常重要的概念,–save 的意思是將這個 package 設定為本次專案的 dependency。

事實上,所謂的 npm 意即node package manager、node 套件管理器,npm 的默認設定是將一個套件 (package) 安裝在 node 模組下。

故當我們在安裝其他人寫的 package 後,必須再設定這個 package 是這個專案的 dependency (依賴模組),告訴這個專案說:這次的專案需要依賴於這個模組才能運作噢!

 

■ 建立Express App – 設定伺服器(Server)與路由(Route)

為了將從頭建立起一個 Express App,接下來我們會設定應用伺服器 (Application Server) 和一個基本的路由 (Route)。

Routing 是把網址 (URL) 轉給特定程序處理的過程,幫助伺服器解析 URL、判斷 URL 路徑與相應的執行動作。

從使用者的角度來看,一個 Route 就是一個 URL,比如 lyrasoft.net/tw/about lyrasoft.net/tw/home

URL 之 所以被稱為 Route,是因為它告訴使用者如何從伺服器拿到資料的路徑。

從應用程式 (applications) 的角度來看,Route 會告訴應用程式什麼時候要做出什麼動作。舉例來說,/about 會告訴應用程式:「請載入About這個頁面的內容。」

被用來訪問一個網站的應用程式、通常稱為客戶(Client) 端,可以把我們的網頁瀏覽器 (Browser) 想成客戶端、而 Routes 就是輸入瀏覽器中的 URLs。

伺服器之所以會知道怎麼送和何時送資料到客戶端,是因為客戶端這邊向伺服器送過去一個 HTTP Request。Request 在這邊是一個專有名詞,當你將URL輸入瀏覽器時,實際上是瀏覽器會在這個URL的位址上送出一個Request給伺服器。

如果客戶端送了一個 Request、而伺服器端這邊有設定好回應的方法時,伺服器就會送回去一個 Response;若伺服器沒設定好 Response 的方法、就會回傳一個Error。

像是「Page Not Found」,表示伺服器找不到相對應的檔案或目錄。上頭顯示的 404,意指 HTTP 狀態碼 (Status Code),用以表示網頁伺服器 HTTP 回應狀態的 3 位數字代碼。2XX 代表伺服器成功接收到客戶端傳來的訊息、4XX 則代表 Client 端訊息有可能錯誤、讓伺服器無法處理。

讓我們來設定一個簡易的 Express.js 伺服器吧!首先用 const express、宣告 express 這個變數載入 express 函式庫,再宣告 app 變數為 express function、建立一個 Express 伺服器;最後告訴伺服器聽取 3000 這個 Port。

簡單來說,Port 就像是電腦的門,一部電腦的 Port 編號從 0 到 65535,共有 65536 個、各有特定的用途。3000 是我們隨意選取的一個 Port,當然你也可以選擇其他編號,一般常用 3000、300x、8000、800x、8089、8080。

1000 以下由於已有大多系統在用,故通常不會使用;也有一些常見的程式會使用固定的 Port,如 MySQL 專門使用 3306,通常也會避開。

然後打開 Node.js Terminal,輸入 Node app.js 啟動 Node。

再打開瀏覽器、在 URL 上輸入 localhost:3000,就可以連線到伺服器。

為了之後更快地確認伺服器成功連線,讓我們在 app.listen 上加上一行訊息 “Example app is running on port 3000!”、並讓訊息在 console 上面印出來。

重新啟動 app.js 檔案後就可以成功看到Console上的”Example app is running on port 3000!”了。這則訊息並不會讓客戶端的使用者看到、僅供開發者參考。

■ 自訂路由(Routing) – 接收請求(Get Request)與回傳回應(Send Response)

回去確認一下瀏覽器。咦?! 明明成功在Console上印出訊息了,伺服器怎麼會說Cannot Get呢? 很簡單,因為我們沒有告訴伺服器接收Request和回傳Response回去的方法阿~讓我們來建立一個路由函數:

如何接收並回應HTTP Request有很多不同的方法,我們在這邊介紹Request最主要的一種方法:「Get Request」。

輸入新的一行程序,告訴伺服器在根目錄(https://hellolynn-2dd1.kxcdn.com/)時需要「Get」資料、並「Response」回送一行字串(String)回去。Node.js 就是 JavaScript 寫成,故字串同樣是用單引號(‘ ‘)包起來。

接下來在 Terminal 先按 ctrl-c 跳出執行程式、再一次輸入 node app.js  (注意每次都要記得這個動作),重新在瀏覽器輸入 localhost: 3000,我們可以發現伺服器果然回傳 “Express is excellent!”這個字串回來了!

讓我們來玩個有趣的嘗試,在Express is excellent!這行字串中加上<h1>Tag:

再一次啟動 app.js、重新整理瀏覽器,可以發現出現的字樣並不是<h1>Express is excellent!、而是加了HTML Header Tag效果的 “Express is excellent!”。

到底發生了什麼事情呢? 因為瀏覽器最初就是設計來展示 HTML,故瀏覽器在接收到伺服器這邊回傳的字串時,是把收到的 ”<h1>Express is excellent!</h1>”解析成 HTML 呈現出來。

● 小練習: 使用GET 回傳有包括 <h1>首頁</h1> 的 html

解答:

 

■ 從URL拿到資料

還記得我們在前面舉例說,/about 會告訴應用程式:「請載入 About 這個頁面的內容。」嗎?

來試試看從 URL 的路徑中讓伺服器拿到資料吧。「/」代表從根目錄拿到資料、「/about」代表可以拿到 About 頁面,也可以往下繼續設定路徑找到 about 下的 about-me 頁面:「/about/about-me」。

 

啟動 app.js、輸入設定好的 URL 路徑,可以看到果真將路徑下的資料傳回來了!

伺服器會從 URL 找到並回傳字串,包括 HTML、JSON 等都是字串的一種。這次在「/blog」路徑下回傳一個 JSON 回應吧。

好玩吧,以下是這次示範的程式碼,來試試看吧!

■ 從req.params拿到參數

我們可以進一步在URL做一些設定、並從 URL 拿到我們要的參數;這些參數的命名可由我們自己命名。首先介紹的 req.params,當伺服器拿到「/post/:id」這個路徑時,回傳id這個參數(parameter)、寫作「req.params.id」。

這時在 URL 輸入/post/(我們設定的參數),就是 /post/:id;比如輸入 /post/12345、req.params.id 就是 12345。 來看看瀏覽器上會出現什麼吧!

req.params 會將命名過的參數以 key-value 的形式存放;比如路徑 /user/:name,name 屬性會存放在 req.params.name。

我們也可以在中間加上字串、並結合兩個參數:

雖然在URL輸入/about/(我們設定的參數)/(我們設定的第二個參數),比如這邊的舉例是 /about/Lynn/pretty 因為中間加了一個字串將兩個參數串在一起,可以發現瀏覽器的結果會有些不同呢!

同樣附上示範程式碼,來試試看吧!

● 小練習:

(1) GET /api/users/1 回傳 json ;

 

(2) GET /api/users/1 回傳 json

 

解答:

 

■ 從req.query拿到參數

透過 req.query 拿到 URL 路徑 ?後面的參數資料,? 後面開始是 JSON 的 key-value 設定。讓我們回傳一個 req.query 參數:

然後在 URL 上輸入/hell?(我們設定的key)=(我們設定的value),舉例為/hell?children=100。

既然說 ? 後面接的是 JSON 的 key-value 設定,那如果我們回傳的就是 JSON 格式呢? 試試看 res.json(req.query)

 

同樣在URL上輸入一樣的格式、? 後面接我們要的參數,舉例為 /gogo?shopping=5,我們可以發現結果是一樣的:

這是為什麼呢? 這是因為在傳送 JavaScript 物件(object)  或陣列 (array) 時, res.send 和 req.json 的結果是相同的。

那我們可以同時利用 req.params 和 req.query 、在 URL 上拿到資料嗎?

由於 JSON format 無法與一般字串接在一起、會印不出來,因此要先把 JSON 轉成字串 (stringify) 再印出來:

 

在 URL 中輸入 /hey路徑、設定 req.params.yo 的參數為 my_dear,再設定 ?name=lynn ,來看看結果會是如何吧:

附上案例程式碼:

● 小練習:GET /api/query?x=123&y=234 把 query 變成 json 傳回去

 

解答:

 

下一集,將為大家持續介紹如何使用 express 的 router 來幫助我們設定路由、使用 nunjucks 模板引擎、使用 body-parser,與 middleware 概念等詳細解說。

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *