前端不斷的演進,更講求畫面快速變化,跳脫傳統傳送資料方式,漸漸改為用 javascript 連接,所以,server 端就負責建立 api,透過串接 api 處理資料。

關於 Api, 就有所謂的 RESTful (Representational State Transfer),RESTful 是某種設計架構的稱呼,方便、有彈性的傳輸資料。後面來會用 node.js 搭配 express 架構 RESTful Api,部署到 server 上,建立一個簡單的留言板。

Demo comment board
Free Heroku 會 sleep,太慢請 reload

安裝 Node.js express

首先先創建資料夾,npm init 安裝 package.json。

// create file
mkdir nodeapi
cd nodeapi
// install package.json
npm init
// install express
npm install --save express

接下來要開始建立 node.js server

// open package.json & add npm start
...
  "scripts": {
    "start": "node index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
...

// create index.js
touch index.js

建立 nodejs server

 以 index.js 作為 node.js server 的起始點,首先引入 express,執行使用 express,這邊先設定好 Port 是 3000,再來建立 get 的 route,路徑是/comments。儲存後執行 npm start,在網址輸入 http://localhost:3000/,這時候會看到畫面顯示 Hello world。

/index.js

const express = require('express');
const app = express();

const port = 3000;

app.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
});

app.listen(port, function() {
    console.log(`server start on http://localhost:${port}, port`);
});

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <h1>Hello!!</h1>
</body>
</html>

建立 mLab account 創建 mongoDB

因為我想試試看串接 mongoDB,這邊選用 mLab 來管理 mongoDB,流程大概是進入 mlab 網站,建立帳戶,再來創建 db,點擊建立 User,設定帳號、密碼、權限。

這邊雖然看似簡單但非常麻煩。

mlab 建立 mongoDB 教學

記得要 create user,後面會依靠這個 username 跟 password 來串接 mongoDB,我因為打錯 dbName,顯示 MongoError: not authorized on dbname to execute command,大概卡了 40 分鐘…。

createmlab
createmlab

首先安裝 mongodb。

npm install --save mongodb

index.js 增加內容

// modify index.js
...
const MongoClient = require('mongodb').MongoClient;

const url = 'mongodb://ian:[email protected]:31323/ian-test';

MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    const dbo = db.db("ian-test");
    const myobj = { name: "john", time: "2018/10/13/00:58", content: "hello, good evening" };
    dbo.collection("comments").insertOne(myobj, function(err, res) {
      if (err) throw err;
      console.log("1 document inserted");
      db.close();
    });
});
...

修改完成後輸入 npm start,如果沒出現 error 就可以打開 collection 觀看,會增加一個 comments 的 collection,點開 comments 會發現剛剛 myobj 資料在裡面。這邊是建立資料邏輯,在 RESTful 會用到 Create,剩下更新 PUT、刪除 Delete、讀取 Get 後面再寫上。

w3c mongoDB 語法教學

mlabData
mlabData

POST Api 創建資料

這邊要下載 body-parser 插件,要對資料格式處理,這邊要使用到是 JSON data。在 index.js 引入 body-parser,使用 bodyParser 對資料轉型別成 json type,建立 post 的 route,我們命名路徑為/comments。

npm install body-parser --save

index.js

...
const bodyParser = require('body-parser');

app.use(bodyParser.json());

app.post('/comments', (req, res) => {
    console.log(req.body);      // your JSON
    db.collection('comments').save(req.body, (err, result) => {
        if (err) return console.log(err)
        console.log('saved to database')
        res.send(req.body);
    });
})

// modify app.listen(3000, () => {});
MongoClient.connect(url, (err, client) => {
    if (err) return console.log(err)
    db = client.db('ian-test')
    app.listen(port, () => {
        console.log('listening on 3000')
    })
})
...

修改完成後重新 npm start,打開 localhost:3000,打開瀏覽器 devtool,在 console.log 貼上這段 fetch post,成功的話會接收到回傳資料,哇嗚,這樣就完成了儲存的 API!!

javascript fetch post

fetch('http://localhost:3000/comments', {
    method: 'post',
    headers: {
        Accept: 'application/json, text/plain, */*',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        name: 'mikessss',
        time: '2018/10/13-02:33:01',
        content: 'ggggggg.'
    })
})
    .then(res => res.json())
    .then(res => console.log(res));

Get Api 取得資料

我們前面成功的建立了儲存的 api,之後的邏輯都大同小異,接收 request,再依照請求方式跟 mongoDB 連接資料。我們這邊的 get api 會拿整個 comments 的資料,如果看不懂 collection.find(),可以看一下 w3c 的 mongoDB 語法教學,非常簡單易懂。

增加完成後,一樣重新啟動,再來載入 http://localhost:3000/comments,就看到我們剛剛儲存進去的所有資料了。

index.js

...

app.get('/comments', (req, res) => {
  db.collection('comments').find().toArray((err, result) => {
    if (err) return console.log(err)
    res.send({data: result})
  })
})

...

Delete Api 取得資料

這邊就建立一個 delete 的網址路徑,我們利用網址:id 來帶參數,方便我們好維運 api。mongoDB 刪除用的是 remove function,假設要用 mongoDB 預設的_id 當作查詢刪除,會多需要使用 ObjectID 處理 value,但如果你是自己用其他物件來查詢,就不用使用 ObjectID。

這邊就不提供 fetch 測試了,推薦使用 postman 測試請求方式,又簡單又快又方便。

postman chrome tool

const ObjectID = require('mongodb').ObjectID;

app.delete('/comments/:id', (req, res) => {
    // use _id need use ObjectID(value)
    const obj = { _id: ObjectID(req.params.id) };
    db.collection('comments').remove(obj, function(err, obj) {
        if (err) throw err;
        console.log('1 document deleted');
        res.send('delete success');
    });
});

Update Api 更新資料

建立 put 的 route,使用 updateOne 來更新資料,前面兩個參數要帶查詢、更新資料。

這樣就完成了 CRUD 的 API 了,下個步驟會建立簡單的畫面,在部署到 server 上,讓我們可以在畫面操作讀取、建立、更新、刪除資料。

app.put('/comments/:id', (req, res) => {
    console.log(req.params.id, req.body);
    const newvalues = {$set: req.body};
    const obj = {_id: ObjectID(req.params.id)};
    db.collection("comments").updateOne(obj, newvalues, function(err, obj) {
        if (err) throw err;
        console.log("1 document update");
        res.send('update success');
    });
})

localhost api file

github 程式碼

部署到 Heroku

部署到 server 上,讓我們未來方便直接串接 api,提醒一下要到 heroku 設定 mLab 的連線,否則會連不到 mongoDB。
(這邊我也卡了 30 分鐘…,安裝 addons 也沒用,是執行下面的 command 才 run 起來)

heroku config:set PROD_MONGODB=mongodb://dbname:[email protected].mlab.com:31323/ian-test

heroku mLab setting

heroku deploy 流程

//login account
heroku login

//use git
git init
git add .
git commit -m "init node"

// create heroku repo
heroku create

// push remote
git push heroku master

heroku ps:scale web=1

heroku open

再來載入 /comments 路徑,pathname/comments,看到 mongoDB 的資料拉!

node api data
node api data

大功告成,接下來就處理好前端串接,畫面互動就可以了。

實作頁面

Demo comment board

完整程式碼

github 程式碼

有問題歡迎詢問,感謝閱讀!!