2017年5月18日 星期四

[JS] Node.JS 開始使用 Express 和 Express-Generator

繼續之前的<Node.JS>記錄。開始了Node.JS的學習,當可以架設到一個簡單Server之後,在Coursera找了一個Node.JS的 Open Course (這應該有三個星期前了)。下一步就是用Express模組來建構同樣的伺服器端程序,Express是一個Node.js 的Web應用程式架構,方便創建各種Web應用、APIs等。今後就會用到它實現旳路由控制(Route),去代替之前要自行寫代碼解析URL中的的請求;用它對模板(Template)的支援,去更方便地回傳HTTP的內容。另外,還會多看幾個模組:Morgan、body-parser,這些稱為Middleware的東西。最後會用Express Generator去生成Express架構。

Express

首先,為你的新專案開啟一個新資料夾,cd到這個資料夾中:
$ npm init  //用npm init開始建立一個專案
$ npm install express --save  //安裝Express, 新增至相依關係清單

例子: server-1.js 。可以看到己經在使用app.get、res.send,去代替url的解析工作和內容顯示:
var express = require('express');
var app = express();

app.get('/', function (req, res) { //當收到 "/" 這個請求時,回應下面的 "Hello World!"
  res.send('Hello World!');
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

METHOD 可以使用的 GET, POST, PUT, DELETE 的作用好比: Read, Write, Append, Delete。
路由定義的結構:app.METHOD(PATH, HANDLER)。其中一種 app.all() 是所有的request都會被觸發,適合處理必需執行的部份。下面的例子中應用到。

Express中的 express.Router 可以用來自建立路由處理程式,之後也可以模組化,例如本身一個.js檔寫的server-2.js 去處理  "http://localhost:3000/dishes/2"  這個請求:

serve-2.js
var express = require('express');
var dishRouter = express.Router();

dishRouter.route('/')
.all(function(req,res,next) {
      res.writeHead(200, { 'Content-Type': 'text/plain' });
      next();
})
.get(function(req,res,next){
        res.end('Will send all the dishes to you!');
})

dishRouter.route('/:dishId')
.all(function (req, res, next) {
    res.writeHead(200, {'Content-Type': 'text/plain' });
    next();
})
.get(function (req, res, next) {
    res.end('Will send details of the dish: ' + req.params.dishId + ' to you!')
})

app.use('/dishes',dishRouter);


可以變成下面例子這樣:先寫好處理 "....../2" 這個部份的 的dishRouter.js 。之後才在server-2.js中被引入,指派去處理 "http://localhost:3000/dishes/......" 的請求。

dishRouter.js
var express = require('express');
var dishRouter = express.Router();

dishRouter.route('/')
.all(function(req,res,next) {
      res.writeHead(200, { 'Content-Type': 'text/plain' });
      next();
})
.get(function(req,res,next){
        res.end('Will send all the dishes to you!');
})

dishRouter.route('/:dishId')
.all(function (req, res, next) {
    res.writeHead(200, {'Content-Type': 'text/plain' });
    next();
})
.get(function (req, res, next) {
    res.end('Will send details of the dish: ' + req.params.dishId + ' to you!')
})

module.exports = dishRouter;


index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});
module.exports = router;
 
server-2.js
...
var routes = require('./routes/index');
var dishRouter = require('./dishRouter');
...
var app = express();
...
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/dishes', dishRouter);...


Express Generator

Express Generator是一個預設好網站架構和模板內容的工具。之後我們會安裝及使用Express Generator生成網頁,重新開始的一個專案:
$ npm install express-generator -g //Express-Generator的全域安裝, 安裝到系統資料夾,為了執行檔,例如下一行的'express')
$ express myServer01  //用express開始建立一個專案node-express-gen
$ cd myServer01
$ npm install .  

這時候Express Generator就會已經預設好架構和內容,預設主要執行的.js 檔是在 myServer01 中的app.js。npm install 會安裝app.js 中需要的相依套件。於是我們已經可以執行這個Server:
$ npm start

以上看到,只要幾句就可以有一個運作的Web網頁Server,之後就可以自行修改app.js 或加入其他static檔案。


Middleware

另外,可以使用其他中介軟體Middleware提供的函數。例如用"morgan"處理Log的顯示,用"bodyParser"解析傳入的請求中的body內容等。

如果不是用Express generator的話,可以先在cd到項目的目錄中安裝
$ npm install morgan --save
$ npm install body-parser --save


例如為上面的例子加入以下語句:
var express = require('express'); //
var morgan = require('morgan'); //處理Log的顯示
var bodyParser = require('bodyParser'); //解析傳入的請求中的body內容

var app = express();
app.use(express.static(__dirname + '/public')); //提供靜態檔案,含有靜態資產的目錄名稱,建立虛擬路徑字首
app.use(morgan('dev')); //為開發過程使用,輸出時用顏色代表回傳狀態
app.use(bodyParser.json()); //解析下面用PUT傳入的json內容

dishRouter.route('/:dishId')
  .all(function (req, res, next) {
      res.writeHead(200, {'Content-Type': 'text/plain'})      next()
  })
  .put(function (req, res, next) {
      res.write('Updating the dish: ' + req.params.dishId + '\n')
      res.end('Will update the dish: ' + req.body.name + 
        ' with details: ' + req.body.description)
  })

...

順帶一題,留意引入不同種類的套件時用 require 的3種形式:
Core: require(fs)
File: require('./dishRouter')
Npm: require('morgan')

暫時記到這裡,之後的課節會用更多的套件去完善網路功能,例如 database、session、cookies、authentication 等等,還有想做一些抓取資料、API 之類的其他Node.JS的用法,都會需要以上的作根基。



1 則留言: