[NodeJS Become A Full Stack Developer] — Express、Router 及 EJS 入門淺談
Introduction & 前言
今天會提到關於 Nodejs 的 Template,如果你在前端有使用過 **Pug(Jade)**,會比較好理解一些,如果沒用過也沒關係,跟著這篇一起練習吧。
Nodejs 的 Template 有許多種,這邊示範的為 EJS。
Summary & 摘要
在前面的文章 [NodeJS Become A Full Stack Developer] — 從0開始 NodeJS 小試身手 我們開啟了全端之路,在入門如何安裝及使用 Nodejs 之後這篇文章就要簡短講解如何快速建立後端環境,並且規劃簡單的架構及使用模板建立多頁面。
老樣子
按照慣例文章開頭還是要講一下什麼是 Express。
跟前端一樣,Nodejs 也有三個比較流行的框架,分別為 Express、Koa 及 Hapi,但你可能會有點疑問,我安裝了這些框架但他們好像沒有幫我弄好環境?
沒有錯,這些框架和前端那些框架有些異曲同工之妙,這三個框架提供了一些更方便的 API 可以使用,但環境必須要自行建立,如果你不想要手動建立環境的話別擔心,可以考慮研究一下 **Express Generator(註1)**,但這邊推薦新手先自行從 0 開始建立環境才能比較了解為什麼 Express Generator 要幫我把環境這樣放。
關於三個框架的好壞這邊稍微提一下(不是專業的分析,有誤還請各路大神見諒),詳細可參考 **如何正確選擇Node框架:Express、Koa還是Hapi**:
優點:三個框架內最小且靈活的框架、學習曲線較低、可客制程度高、可擴展性高
缺點:需要大量的手動建置,且框架對於組織需要非常明確。
優點:由 Express 原班人馬開發,在 koa2 開始使用了 async/await,在非同步控制上,代碼可讀性更高、性能好。
缺點:Koa 的社群相對較小(現在似乎不一定了)、和 Express 的插件不相容。
優點:issues 數量少,維護與關注狀態都非常好、對於路由配置更加詳細。
缺點:配置上結構較複雜。
註1:之後會再寫一篇如何使用 Express Generator 快速建立 Nodejs 專案。
起手式一
首先建立一個新專案資料夾,然後進入這個專案資料夾:
1 | $ mkdir express-example |
到目前為止在專案資料夾應該會出現 node_modules package.json package-lock.json(註2)。
註2:關於 node_modules package.json package-lock.json 前面文章提到過很多次,這邊再稍微講一下,*node_modules 是放各種套件的地方,package.json 則是紀錄你這個專案使用了什麼套件,所以之後把專案上傳可以不用上傳 node_modules 只需要讓下一個人拿到 package.json 即可安裝你之前安裝過的所有套件,最後 package-lock.json 則是紀錄套件使用的版本號。*
起手式二
裝好之後在專案底下建立 app.js 並且輸入以下內容:
1 | // app.js |
之後在終端機輸入 node app.js
就可以看見終端機的訊息:
接著在網址上輸入 http://localhost:3000/
就會出現下面的訊息:
起手式二 - 補充
上面我們可以成功在網頁上顯示 Hello Express! 聰明的你一定想得到是透過 response.send()
這個方法,這邊就要講解關於 request
及 response
。
request
為 從使用者那邊發送過來的請求,response
為服務器這端發送回去的回應,我們可以透過 request
拿到一些使用者的請求及資訊,比方說 request.route
、req.param('key')
及 req.body.xxx
等等。
這邊試著將 app.js 的程式碼改為以下:
1 | // app.js |
你會看見 request
有許多資訊可以拿取:
後面會再提到如何顯示 HTML 在頁面上。
規劃及準備
前面了解到基本路由的概念,這時候我們就要開始規劃怎麼更改我們的專案架構,可以想像我們之後會有很多路由,我們可以把路由另外放一個資料夾,然後再透過 app.js 引入進來。
先在專案建立資料夾 routes(放路徑) 然後在資料夾內在建立 index.js。
這時候你的架構會長這樣:
接著打開 /routes/index.js
之後把內容改為以下:
1 | // /routes/index.js |
然後把 app.js 改寫為以下:
1 | // app.js |
這樣我們就把 index 的路由都統一放到 /routes/index.js
去管理了,如果還不太明白,我們再多建立一個 router,一樣在 /routes
底下建立一個 user.js
,然後內容改為以下:
1 | // /routes/user.js |
接著一樣在 app.js 引入路由:
1 | // app.js |
緊接著在終端機輸入 node app.js
啟動網頁,分別輸入網址 http://localhost:3000/
、http://localhost:3000/detail
、http://localhost:3000/user
及 http://localhost:3000/user/user-edit
:
懶人包:建立 routes 資料夾,每次要新增一個路由分類時,先到 routes 資料夾底下新增,例:user、member 或 login 等等,然後再到 app.js 分別引入,例:var indexRouter = require('./routes/index');
或 var userRouter = require('./routes/user');
然後在使用路由 app.use('/', indexRouter);
及 app.use('/user', userRouter);
。
EJS
快速導覽
學玩怎麼使用 router 之後這邊就要提到,後端寫好一支 API 可能是吐回一段文字,可能是直接渲染一個畫面,也可能是一段 JSON,前面我們使用的 response.send('xxx');
這個意思就是吐一段文字回去給瀏覽器,
這時候你肯定會想我寫了一個 HTML 想渲染給使用者看,我不就要寫 response.send('<h1>我是標題</h1>');
,其實不用這麼麻煩,這邊要介紹到的 EJS 就是方便你渲染及動態帶入參數。
另外 Template 的好處應該大家也都知道了,如果我今天有十支檔案都有 header,假如 header 有個地方要修改,不用十支都修改,只需要修改共用的 Template 即可。
快速起手
在開始動作之前我們先在終端機輸入 npm i ejs-locals -S
(註3) 安裝 EJS
。
接著在專案資料夾底下新增 /views/index.ejs
及 /views/user.ejs
然後把 app.js
改為下列內容:
1 | // app.js |
然後把 /views/index.ejs
的內容改為下列的內容:
1 | <!-- /views/index.ejs --> |
然後再回到 /routes/index.js
改為下列內容:
1 | // /routes/index.ejs |
在上面我們把原本的 response.send()
改為 response.render('index')
意思就是把 views 底下的 index.ejs 渲染回去給瀏覽器,那為什麼 nodejs 會知道我們要選染哪一隻檔案回去呢?因為上面我們使用了下列的程式碼:
1 | // app.js |
上面的 path 就是 nodejs 原始的 API,而 __dirname 我們在前面的 [NodeJS Become A Full Stack Developer] — 從0開始 NodeJS 小試身手 有提到,這邊大概的意思就是當我使用 response.render('index')
的時候,會自動幫我抓路徑 response.render('index') => response.render('目前路徑/views/index')
,最後一行則是把目前的 view 引擎設定為 ejs。
現在停止終端機的指令,重新輸入 node app.js
打開瀏覽器輸入 http://localhost:3000/
吧,會出現下面的畫面就代表成功了:
註3:這邊建議安裝 ejs-locals 而非 ejs 因為前者多了更多的 API 可以使用
帶入參數
但是通常我們後端在渲染畫面的時候,必定會先去資料庫拿資料,在渲染畫面,而參數帶入的方法也很簡單,只需要在渲染的時候加進去即可,接著再去 ejs 顯示出來,找到 /routes/user.js
這隻檔案,並且改寫為下列內容:
1 | // /routes/user.js |
接著也把 /views/user.ejs
改寫一下吧:
1 | <!-- /views/user.ejs --> |
聰明的你會立馬發現 <%= username %>
這個新寫法,其實這就是模板的原理,在要替換的地方使用變數,再透過更新資料去觸發畫面更動,這也是 Vue 的原理,像六角學院校長說的,並非魔術!
接下來重新啟動終端機輸入 node app.js
一樣打開瀏覽器輸入 http://localhost:3000/user
你會發現神奇的大雄被帶進來了,如下圖:
if-else
另外 ejs 可以跟 pug 一樣寫 js 在上面,所以我們也可以寫判斷,把 /views/user.ejs
改寫為下列內容:
1 | <!-- /views/user.ejs --> |
接著一樣重新啟動終端西,執行 node app.js
之後打開瀏覽器輸入 http://localhost:3000/user/user-edit
會出現下面的內容:
我們可以在參數使用 Boolean 然後在渲染時依靠 true/false 去決定是否顯示內容,也可以用迴圈的方式把資料給渲染出來,這和我們使用 JS 來渲染畫面到 HTML 是大同小異的。
關於更多的 ejs 用法可以參考 ejs docs
範例
這邊附上簡單的 express-example,裡面包含簡單的 routes 拆分 及 ejs 的模板使用。
另外有補上簡單的靜態資源引入,用法很簡單,只需要在 app.js 加上一行 app.use(express.static('public'));
即可,接著在需要引入的地方只需要直接把路由從 public 接著打下去即可,因為預設會去找 public 這個資料夾,例:<img src="/images/soGood.jpeg">
。
GitHub: 傳送門
Conclusion & 結論
這篇文章原本想簡短介紹 EJS,但因為提到了 Router 不得不在最後把文章標題從 Express 及 EJS 入門淺談 改為 Express、Router 及 EJS 入門淺談,原本想長話短說,不知不覺又越寫越長,不過到這邊也大致對 nodejs 的環境有些許了解了,之後的篇章將會繼續講解如何使用 nodejs 的 Cookie 及 Session。