iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 20
1
Modern Web

還在想要買哪一堂線上課程嗎?培養看文件的習慣吧!用 MDN 文件學後端:NodeJS & MongooseDB系列 第 28

28日: Express Tutorial 2: Creating a skeleton website ( 結構 - app.js & routes & views 、 練習題 、 結語 )

出處

app.js

這個檔案建立一個 express obj ( 習慣命名為 app , 也比較方便 ), 還有一些 middleware 有關及其他的設定, 來 export module 。 下方節錄出來的一些 code 就在處理上述的任務

var express = require('express');
var app = express();
...
module.exports = app;

回到 www 進入點檔案 ( 上一篇文章提到的 ) , 這裡就是 export 的來源

現在來仔細瞧瞧 app.js 。 首先用 require()import 一些 libraries , 大部分上篇文章都提到了, 其中有一個 path , 用來解析檔案路徑

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

接著我們從 routes 目錄 require() modules ( 目前一樣還是在討論 app.js 這支檔案喔~ ):
我們會新增檔案來處理書本相關的 routes , 這時就會擴充這個 app 的 skeleton

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

Note: 這時我們 import module, 但我們實際上還沒用到 routes ( 下方文章會討論 )

一堆 require() 之後, 用 express module 建立 app obj , 然後設定 view engine ,這邊有兩步。
首先設定 views 值, 指定存放 templates 的資料夾 ( 這裡是 /views ) ; 接著設定 view engine 值, 指定 template library ( 這裡是 pug )

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

再來設定置入 req handling chain 的 mw libraries , 使用 app.use() 。 這些第三方 libraries 在前面就有 import 了, 此外我們還用 express.static mw 來使 Express 乘載放在 /public 的靜態檔案

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

現在, 其他的 mw 也準備就緒, 我們要來新增 route-handling 到 req handling chain:

app.use('/', indexRouter);
app.use('/users', usersRouter);

Note: 上方我們所指定的 ( / & /users ) , 都帶有前綴去定義 routes 。 如果有個 /profileusers module 拿來 import 定義成為一個 route , 那麼要這樣存取: /users/profile 。 後續會有更多的討論

最後的 mw 新增一些回應 err & 404 的處理

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

現在 Express app obj 全部設定完畢, 最後的步驟就是 exports ( 這樣做允許 app.js/bin/www import )

Routes

以下是 /routes/users.js ( route 檔案架構都很相似, 這裡略過 /routes/index.js ) , 第一行我們很熟悉了, 第二行則是與先前不同 , 改成建立 express.Router obj , 接著指定一個 route , 最後 export ( 這邊是要給 app.js import , 跟上面的不同 )

var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});

module.exports = router;

這個 route 定義了一個 callback , 當 HTTP GET req 偵測到 pattern 正確吻合 ( /users ( app.js 設定的 ) 加上 / ( 這邊設定的 ) , 也就是 /users/ ) 就會被呼叫。
Note: 啟動 server 然後點看看 (http://localhost:3000/users/) , 我們應該會看到 'respond with a resource' 這段訊息 , 如果我們更改文字 ( 或加入 HTML tag ) 重啟 server 後重整瀏覽器 , 畫面也會跟著改變

值得一提的是: callback 含有第三個參數 next , 且是個 mw function 而非簡單的 route callback 。 雖然這段 code 沒有現在使用 next, 但之後如果要在 / 路徑增加多重 route 處理就有可能會用到

Views (templates)

views templates 被存放在 /views 資料夾下, 副檔名為 .pugResponse.render() 是用來 render obj 內的變數到 template 上, 並傳遞結果作為 res 。 下方是 /routes/index.js 的 code, 可以看到 route render 一個名為 title 的變數到 index template 裡

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

與之相對應的 template ( index.pug ) 顯示如下。 我們將會在後續討論更多相關語法, 現在只要知道這個 title 變數被安插進指定 template 的行為就好

extends layout

block content
  h1= title
  p Welcome to #{title}

Challenge yourself

自我練習: 建立新 route /routes/users.js , URL /users/cool/ 的頁面要顯示 "You're so cool"
點選右邊連結看有沒有完成這項練習 (http://localhost:3000/users/cool/)

Summary

  • 了解資料夾結構
  • 知道怎麼用 node 執行 server
  • 最重要的: 了解專案如何構成, 能夠有邏輯的進行更動或新增 routes & views

下一節, 要來改動 skeleton, 讓它像一個圖書館網站


上一篇
27日: Express Tutorial 2: Creating a skeleton website ( 結構 - package.json & www file )
下一篇
29日: Express Tutorial 3: Using a Database (with Mongoose) ( 概覽 、 簡述資料庫互動 、 有哪些 ODM/ORM )
系列文
還在想要買哪一堂線上課程嗎?培養看文件的習慣吧!用 MDN 文件學後端:NodeJS & MongooseDB30

尚未有邦友留言

立即登入留言