最近心血來潮又把 express 玩了一下,寫篇文章來紀錄一下整個過程,會用到的工具如下:
首先安裝 express-generator,這是一個可以自動產生 express 需要內容的工具
$ sudo npm i -g express-generator
安裝好之後,我們切換到我們想要的目錄來產生專案資料夾,我選用 twig 當作我的樣板引擎,我在 PHP 使用 CI 的時候也是選用同一個引擎,可以無痛轉移
/var/www $ sudo express -v twig project /var/www $ cd project /var/www/project $ sudo npm i /var/www/project $ sudo npm i orm mysql --save
專案目錄產生後,我們可以使用 nodemon 來監控目錄,也可以達到修改檔案後自動重起的效果
/var/www/project $ sudo nodemon bin/www
這時候打開 http://10.10.10.16:3000
(我的 vm 測試 IP)就可以看到預設網址,如果希望改 port 的話可以在 env 設定 port,或者直接去改 bin/www
這個檔案
打開 app.js
這是預設的內容
var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var index = require('./routes/index'); var users = require('./routes/users'); var app = express(); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'twig'); // uncomment after placing your favicon in /public //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/', index); app.use('/users', users); // catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // 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'); }); module.exports = app;
所有的動作都在這隻 app.js 設定,我們來建立一個 product routes 檔案
routes/product.js
const express = require('express'); const router = express.Router(); router.get('/', function(req, res, next) { res.render('product/index'); }); module.exports = router;
view/product/index.twig
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h3>This is product page</h3> </body> </html>
將 app.js
加上這個 routes 的設定
app.js
var index = require('./routes/index'); var users = require('./routes/users'); var product = require('./routes/product'); var index = require('./routes/index'); var users = require('./routes/users'); var product = require('./routes/product'); app.use('/', index); app.use('/users', users); app.use('/product', product);
這時網址改成 http://10.10.10.16:3000/product
,就會看到 This is product page 這幾個字
接下來我們進行資料庫的串連,在 MySQL 內建立一個叫 express
的資料庫,另外建立一個 products
的 table 並且塞入資料
CREATE TABLE `products` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(50) NOT NULL ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_unicode_ci;
接下來我們來設定資料庫連接,因為我不喜歡全部的東西都塞在 app.js
,所以我另外開一個資料夾來放設置檔
config/db.js
module.exports = (app, orm) => { app.use(orm.express("mysql://root:123456@127.0.0.1/express", { define: function(db, models, next) { models.product = db.define('products', { id: Number, name: String }); next(); } })); };
修改 app.js 啟動這個設定,只要放在 app
以及 orm
初始化後即可
app.js
require('./config/db.js')(app, orm);
我們先將 routes/product.js
修改成以下內容,變可以從網址先看到結果
const express = require('express'); const router = express.Router(); router.get('/', function(req, res, next) { req.models.product.all((err, data) => { res.json(data); }) }); module.exports = router;
http://10.10.10.16:3000/product
[{"id":1,"name":"product a"},{"id":2,"name":"product b"}]
這是最基本的用法,但我覺得這樣可重複利用性太低了,所以我們來建立類似 model 機制吧
routes/product.js
const express = require('express'); const router = express.Router(); const Product = require('../model/product.js'); router.get('/', async(req, res, next) => { try { const product = new Product(req.models.product); res.json(await product.getAllNews()); } catch (e) { res.send(e); } }); module.exports = router;
model/product.js
class Product { constructor(model) { this.model = model } async getAllNews() { return new Promise((resolve, reject) => { this.model.all((err, data) => { if (err) { reject(err); } resolve(data); }) }) } } module.exports = Product;
這樣的執行結果會一模一樣,但把東西拆乾淨模組化了,再修改一次在 view 呈現吧
routes/product.js
const express = require('express'); const router = express.Router(); const Product = require('../model/product.js'); router.get('/', async(req, res, next) => { try { const product = new Product(req.models.product); res.render('product/index', { products: await product.getAllNews() }); } catch (e) { res.send(e); } }); module.exports = router;
views/product/index.twig
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h3>This is product page</h3> {% for product in products %} <div>product: {{ product.name }}</div> {% endfor %} </body> </html>
以上就是這兩天試玩 express
的整理,沒有實現所謂的 controller 部份,就先把 routes 當 controller,當然一定會有更多更好的方法,再慢慢探索,在此也感謝陳默司大大的指導