- Nuxt.js Fundamental ตอนที่ 0 - พื้นฐานการเขียนเว็บด้วย Nuxt.js
- Nuxt.js Fundamental ตอนที่ 1 - เริ่มต้นกับ Nuxt.js
- Nuxt.js Fundamental ตอนที่ 2 - สร้าง Nuxt.js ด้วย create-nuxt-app
- Nuxt.js Fundamental ตอนที่ 3 - การกำหนด Routing
- Nuxt.js Fundamental ตอนที่ 4 - Nuxt.js Concept
- Nuxt.js Fundamental ตอนที่ 5 - Nuxt Content และ Async Data
- Nuxt.js Fundamental ตอนที่ 6 - การ Fetch ข้อมูลจาก API
- Nuxt.js Fundamental ตอนที่ 7 - การใช้งานร่วมกับ Vuex Store
- Nuxt.js Fundamental ตอนที่ 8 - การทำระบบ Authentication
- Nuxt.js Fundamental ตอนที่ 9 - การ Deploy Nuxt.js
- Nuxt.js Fundamental ตอนที่ 10 - การทำ Internal API และ Middleware
- Nuxt.js Fundamental ตอนที่ 11 - ทำ SEO และ Meta tags
- Nuxt.js Fundamental ตอนที่ 12 - ทำ Workshop เว็บ Portfolio
Nuxt.js Fundamental ตอนที่ 10 - การทำ Internal API และ Middleware
เขียนวันที่ : Aug 25, 2020
(อัพเดท : Mar 20, 2022)
ต่อมาขอเสริมเรื่องการทำ Internal API กันซักนิด ต่อยอดจาก ตอนที่ 8 - ทำระบบ Authentication
จากตอนก่อนหน้านี้ ผมใช้ API ที่อยู่อีก Server นึง ทีนี้ ถ้าตัว Nuxt.js อยากให้ API อยู่ที่เดียวกันกับตัว Nuxt Page ปกติเลย ทำได้มั้ย?
คำตอบคือทำได้ครับ
serverMiddleware
ตัว serverMiddleware ทำให้เราสามารถกำหนด API ได้เอง และส่วน API ก็สามารถเขียนได้แบบ style ของ Express.js เลยครับ
ตัวอย่างเช่นไฟล์ nuxt.config.js
export default {
serverMiddleware: [{ path: '/api', handler: '~/api/index.js' }]
};
- เราแค่ระบุเป็น Object
path
และhandler
function ในserverMiddleware
- ส่วนไฟล์
handler
ก็สามารถไว้ที่โฟลเดอร์api
(สร้างใหม่ หรือใช้ชื่ออื่นๆ ก็ได้)
ทีนี้ เราก็มาสร้างโฟลเดอร์ api
ไว้ที่ level เดียวกับ pages
หรือ components
โดยข้างในมีไฟล์ index.js
ครับ
const express = require('express');
const app = express();
app.get('/hello', (req, res) => {
res.json({ message: 'Hello from serverMiddleware' });
});
module.exports = app;
ติดตั้ง
express
ด้วยnpm install express
ก่อนนะ ถ้าใครรันไม่ได้
ทีนี้ พอเรากำหนด แบบนี้ เราก็สามารถเข้าถึง http://localhost:3000/api/hello ก็จะแสดงผล {message: 'Hello from serverMiddleware'}
ครับ
เพราะเรากำหนดใน serverMiddleware
ว่า path
คือ /api
และในไฟล์ api/idnex.js
เรากำหนด app.get('/hello')
ฉะนั้น path มันก็จะต่อกันเป็น /api/hello
เหมือนกับเราใช้ Express แบบนี้
const router = express.Router();
router.get('/hello', (req, res) => {});
app.use('/api', router);
สร้างไฟล์ api/auth.js
ทีนี้มาดูการใช้งานจริง ผมก็อปไฟล์ server.js
จากตอนที่ 8 มาดังนี้
const express = require('express');
const cors = require('cors');
const app = express();
const router = express.Router();
app.use(cors());
app.use(express.json());
const user = {
id: 1,
username: 'john',
email: 'john@doe.com',
name: 'John Doe'
};
router.get('/me', (req, res) => {
return res.json({
data: {
user
}
});
});
router.post('/login', (req, res) => {
const { email, password } = req.body;
// query db.
if (email === 'admin@admin.com' && password === '123456') {
return res.json({
data: {
user,
token: 'THIS_IS_TOKEN'
}
});
} else {
return res.status(401).json({
message: 'Invalid Password'
});
}
});
app.use('/api', router);
app.listen(12345, () => {
console.log('Mock API start on port 12345');
});
จากนั้น ผมทำการปรับแก้ บางส่วน คือ
- app.use('/api', router);
- app.listen(12345, () => {
- console.log('Mock API start on port 12345');
- });
+module.exports = {
+ path: '/api',
+ handler: app
+}
จากโค๊ดจะเห็นว่า ผมใช้เป็น
module.exports = {
path: '/api',
handler: app
};
- เพราะ
serverMiddleware
กำหนดให้ Object เป็นpath
กับ functoinhandler
- และเอา
app.use('/api', router)
ออก เนื่องจากเรากำหนดในpath: '/api'
แทน ก็เลยเหลือแค่app.use(router)
app.listen
ก็ไม่ต้องใช้แล้วครับ เพราะเราไม่ได้ start server แยก
สุดท้ายไฟล์ api/auth.js
ก็จะได้แบบนี้
const express = require('express');
const cors = require('cors');
const app = express();
const router = express.Router();
app.use(cors());
app.use(express.json());
const user = {
id: 1,
username: 'john',
email: 'john@doe.com',
name: 'John Doe'
};
router.get('/me', (req, res) => {
return res.json({
data: {
user
}
});
});
router.post('/login', (req, res) => {
const { email, password } = req.body;
// query db.
if (email === 'admin@admin.com' && password === '123456') {
return res.json({
data: {
user,
token: 'THIS_IS_TOKEN'
}
});
} else {
return res.status(401).json({
message: 'Invalid Password'
});
}
});
app.use(router);
module.exports = {
path: '/api',
handler: app
};
ต่อมาที่ไฟล์ nuxt.config.js
ก็ปรับแก้ serverMiddleware
อีกนิด เป็นแบบนี้
export default {
serverMiddleware: ['~/api/auth.js']
};
เราสามารถกำหนด
serverMiddleware
เป็น string ก็ได้ หรือ Object ก็ได้ (ถ้าเป็น string ก็ต้องเป็นไฟล์ที่เรามี Objectpath
และhandler
นั่นเอง ไม่งงเนอะ)
ทีนี้ เราก็สามารถใช้ API ได้แบบเดียวกันกับตอนที่ 8 ได้เลย โดยที่ไม่ต้อง Start server แยก ที่ port 12345 แล้ว ก็ใช้ port เดียวกันกับเว็บปกติเลยคือ 3000
ทดลองเข้า http://localhost:3000/api/me แล้วดูผลลัพธ์
Middleware
ทีนี้มาดูเรื่องของ Middlware กันบ้างครับ จริงๆ ในตอนที่ 8 เราจะเห็นว่ามีการกำหนด Middleware ในหน้า Page เช่น
<script>
export default {
middleware: 'auth'
};
</script>
จริงๆแล้ว Middlware มันก็คือ function นี่แหละครับ ที่จะรันก่อน page มัน render เราสามารถสร้าง middlware แบบ global แชร์กันได้ โดยสร้างไว้ในโฟลเดอร์ middlware
นั่นเอง
ตัวอย่าง middlware function (args ตัวแรกที่ถูกส่งไปคือ context
) เราสามารถเข้าถึงค่า context
ได้ เช่น handle ว่าเป็น server หรือ client หรือ get params เป็นต้น
เช่น ผมสร้าง middlware/logger.js
ขึ้นมา
export default function (context) {
console.log('Logging....');
}
ทีนี้ถ้าอยากใช้ middlware นี้ ก็แค่กำหนดใน page แบบนี้
<script>
export default {
middleware: ['logger', 'auth']
};
</script>
ชื่อ Middleware ก็ตามชื่อไฟล์เลย
นอกจากนี้เราก็ยังสามารถสร้าง Middlware แบบ anonymous ใช้แค่ที่เดียวแบบนี้ได้
<template>
<h1>Secret page</h1>
</template>
<script>
export default {
middleware({ store, redirect }) {
// If the user is not authenticated
if (!store.state.authenticated) {
return redirect('/login');
}
}
};
</script>
รายละเอียดเพิ่มเติมเกี่ยวกับ Middleware อ่านได้ที่นี่
Hints & Questions?
- Internal API ถ้าเราทำการ build แบบ
static
และเป็น modespa
มันจะรันได้มั้ย? - ลองใช้ Internal API ร่วมกับ connect ดูครับ
serverMiddleware
กับmiddleware
ใน Page เหมือนกันมั้ย?