為什麼學Node.js還要使用Express這個框架呢?
其實我自己的想法是, 框架本身畢竟是由一群人維護
身為一般的開發者, 應該專注在開發功能, 其他的只要跟著框架的規則
很多自己做要花很多時間的事情, 幾行之內就結束
不管是Express或是Koa2都可以, 先讓自己專注在功能開發上吧!
使用 Express 應用程式產生器 (Express Generator)
打開終端機
輸入npm install express-generator -g
切換終端機的目錄到桌面cd Desktop/
接著開始產生Express專案
// myapp 是專案名稱, 你可以自行替換成想要的
express --view=pug myapp
接者會跑一堆字出來之後
create : myapp
create : myapp/package.json
create : myapp/app.js
create : myapp/public
create : myapp/public/javascripts
create : myapp/public/images
create : myapp/routes
create : myapp/routes/index.js
create : myapp/routes/users.js
create : myapp/public/stylesheets
create : myapp/public/stylesheets/style.css
create : myapp/views
create : myapp/views/index.pug
create : myapp/views/layout.pug
create : myapp/views/error.pug
create : myapp/bin
create : myapp/bin/www
接下來切換到自己剛剛建立的專案底下
// && 是可以等前面的指令執行完之後, 接著執行後面的
// npm install是幫你把目前這個專案所需要的套件通通安裝
// 專案所需要的套件都會放在package.json內
cd myapp && npm install
接下來就可以直接透過輸入以下指令來啟動Express
node bin/www
通常我會習慣另外開一個models的資料夾在專案內
專門在放處理資料庫相關的程式碼
// 建立models目錄並且進去
// mkdir => make directory, cd => change directory
mkdir models && cd models
// 建立一個 index.js 的檔案
touch index.js
覺得指令麻煩也可以直接用編輯器建立!
只是想說用用指令, 看起來比較帥(?
接著可以用編輯器去編輯這個 index.js
這裡很推薦一定要使用index.js這個檔名
因為之後再引入的時候, 語法寫起來比較好看!
後面會再提到一次不用擔心
/*jslint node: true */
'use strict';
// process.env 是 Node.js 的環境變數
// 通常我會習慣將一些比較機密的東西放在環境變數中
// 這樣就算專案外流, 機密的資料也不會一起外流出去
if (!process.env.mongoHost) {
console.error('[model]', 'process.env.mongoHost is not set!'); process.exit(0);
}
if (!process.env.mongoAuth) {
console.error('[model]', 'process.env.mongoAuth is not set!'); process.exit(0);
}
// 引用MongoDB官方自己的程式(library)
const MongoClient = require('mongodb').MongoClient;
// MongoDB在網路上的位址
const host = process.env.mongoHost;
// 驗證資料庫用的字串, 如果不啟用驗證, 每個人都可以連資料庫, 超不安全
const auth = process.env.mongoAuth;
// 資料庫名稱
// process.env.mongodbDatabase || '/fakeig'
// => 就是如果沒有process.env.mongodbDatabase這個值的話, 預設用 'fakeig'
const database = process.env.mongodbDatabase || '/fakeig';
// 連接MongoDB用的URI
// 這是連接MongoDB固定用的格式
// 使用mlab會讓你自己去定義一組帳號密碼, 用來驗證MongoDB
const schema = 'mongodb://' + auth + host + database;
// 設定MongoDB的一些常用設定
const opts = {
keepAlive: 1,
connectTimeoutMS: 30000,
poolSize: 5,
native_parser: true,
autoReconnect: true,
w: 0
};
// 自己將 MongoClient 的東西額外包裝起來
let mongoNative = {
_db: null,
connect: function connect() {
return MongoClient.connect(schema, opts)
.catch((err) => {
console.error('[x] mongodbDatabase:', process.env.mongodbDatabase);
console.error('[x] host:', host);
console.error('[x] schema:', schema);
console.error('[x] Get Database Error:', err);
process.exit(0);
});
},
getDatabase: function getDatabase() {
return this._db;
},
setDatabase: function setDatabase(db) {
this._db = db;
}
};
module.exports = mongoNative;
目錄結構會變成以下, 多了models這個目錄
.
├── app.js
├── bin
│ └── www
├── package.json
├── models
└── index.js
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.pug
├── index.pug
└── layout.pug
稍微介紹一下什麼是API(Application Programming Interface)
簡單來說就是你提供一個功能給網頁或是APP呼叫
例如: 註冊會員
我們就可以設計一個API, 網址是http://xxxx.com/api/v1/auth/register 這樣
接下來寫個會員登入的功能吧!
我們會額外多一個路徑叫做ap1/v1
這樣API的網址就會變成 http://xxxx.com/api/v1/auth/facebook/login 這種
會用這樣設計的原因是假如有一天需要重大更新
就可以把v1切換成v2
這樣會比較有彈性!
cd ~/Desktop/myapp/routes
mkdir v1
cd v1
touch index.js
routes/index.js
routes/index.js 是每個進來的API請求都會先經過這隻檔案
這隻檔案再依據api/v1/ 後面不同的路徑, 導向給不同的程式去處理
/*jslint node: true */
'use strict';
const express = require('express');
const router = express.Router();
const cors = require('cors');
const db = require('../models').getDatabase();
// 將v1內的index.js引入
// v1內的index.js用途是將api/v1後面接的路徑, 導向給正確的程式去處理
// ex: api/v1/auth => 導向給v1/auth.js去處理
const v1 = require('./v1');
// 這裡是安全性的考量, 只允許http的GET/POST/PUT/DELETE
const ALLOWED_METHODS = ['GET','POST','PUT','DELETE'];
// 這個是允許跨網域的資源存取
router.use(cors());
router.use((req, res, next) => {
if (!req.body.hasOwnProperty) req.body.hasOwnProperty = Object.prototype.hasOwnProperty;
if (ALLOWED_METHODS.indexOf(req.method) === -1) {
return res.status(405).json({ err: 'Not allowed method' });
} else {
console.log(req.method, req.url, "body:", JSON.stringify(req.body), "params:", JSON.stringify(req.params), "headers:", JSON.stringify(req.headers));
next();
}
});
// 把網址路徑是api/v1的都導向給v1/index.js去處理
router.use('/api/v1', v1);
module.exports = router;
這篇實在太多東西, 會分成兩至三篇, 會再重新講解一些並總結!