503301

  • 能夠在伺服器上面運行 JavaScript 的應用平台環境
  • NVM(Node Version Manager)
    • 處理專案時需要不同的 Node 版本來執行(因有些 npm 模組有版本相容性問題)
    • 下載
      1
      curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash

開始一個專案

  • npm init
  • package.json 的 scripts 中新增”start”指令
    • "start": "node index.js"
  • npm run start

fs(File System)模組

  • 取得 fs
1
const fs = require('fs')
  • 讀取檔案
    • 同步 readFileSync(檔案名稱, 編碼)
    • 非同步 readFile(檔案名稱, 編碼, 要做的處理)
    • Promise
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//同步讀取
try{
const data = fs.readFileSync('hello.txt', 'utf8');
console.log("檔案內容:", data);
} catch(err){
console.log("讀取檔案錯誤:", err)
}

//非同步讀取
fs.readFile('hello.txt', 'utf8', (err, data) => {
if(err){
console.log("讀取檔案錯誤", err);
return;
}
console.log("檔案內容:", data)
})

//promise版本
const fsPromise = require('fs').promises;
async function readAndWriteFile(){
try{
const content = await fsPromise.readFile('hello.txt', 'utf8');
await fsPromise.writeFile('hej.txt', content + '\n new new world~~~~');
console.log("done");
} catch(err){
console.error("something wrong:", err)
}
}
readAndWriteFile();
  • 路徑資訊
1
2
3
4
5
6
7
const path = require('path');

const fullPath = path.join(__dirname, 'files', 'hello.txt');
console.log("檔案名稱:", path.basename(fullPath));
console.log("副檔名:", path.extname(fullPath));
const pathInfo = path.parse(fullPath);
console.log("路徑資訊:",pathInfo);
  • 解析 url
1
2
3
4
5
const myUrl = new URL('https://jsonplaceholder.typicode.com/comments?postId=1')
console.log('主機名:', myUrl.pathname)
console.log('路徑名:', myUrl.pathname)
console.log('搜尋參數:', myUrl.searchParams.get('postId'))
console.log('完整搜尋字串', myUrl.search)

建立基本 http 伺服器

  • 取得 http
1
const http = require('http')
  • 定義 server
    • http.createServer 設定 server
    • res 設定內容
      • res.setHeader 設定網頁內容/類型
      • res.writeHead 網頁狀態碼
      • res.send 寫入 html 內容
      • res.end
    • req 取得網址
      • req.url
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/json')

if(req.url === '/'){
res.writeHead(200);
res.end(JSON.stringify({ message: 'Welcome to Home Page' }))
} else if(req.url === '/api/users'){
res.writeHead(200);
res.end(JSON.stringify({ users: ['user1', 'user2']}))
} else {
res.writeHead(404);
res.end(JSON.stringify({message: 'not found'}))
}
})
  • 監聽
    • server.listem(port)
1
2
3
server.listen(3200, () => {
console.log('伺服器運行在 http://localhost:3200/')
})

nodemon

它會監視你的程式碼有無任何更改,並自動重新啟動服務,這時只要刷新你的瀏覽器就能看到改動

  • 下載 npm install --save-dev nodemon
  • 修改 package.json
    • 在 scripts 中新增 "dev": "nodemon index.js"

npm 下載方式

  • 下載時會出現在 package.json 中的"devDependencies"
  • 使用npm install --production下載非開發版本需要的
    • 用於非開發版本,因為 nodemon 只用於開發,所以下這個指令不會安裝 nodemon
  • 部署時使用

Express

  • 下載 npm install express
  • 拿出 express
1
const express = require('express')
  • 定義
1
2
3
4
const app = express()
app.get('/', (req, res) => {
res.send("<h1>hello world!!!</h1>")
})
  • 監聽
1
2
3
app.listen(3200, () => {
console.log("伺服器運行在:http://localhost:3200/")
})

Middleware

Middleware 是 Express 處理 HTTP 請求的中間處理層,可執行任何任務

  • 宣告
1
2
3
4
const firstMiddleware = (req, res, next) => {
console.log("111111")
next()
}
  • 使用 use()
1
app.use(firstMiddleware)

使用情境

logger 通常放所有頁面之前

  • 驗證/權限判斷
    • 新增判斷的 function
      • 把 function 帶入 .get() 的參數裡
      • req.query取得網址資訊(/users 後面的?以後)
1
2
3
4
5
6
7
8
9
10
11
12
13
app.get('/users', auth, (req, res) => {
res.send("<h1>Users List</h1>")
})

function auth(req, res, next) {
// 網址是/user?admin=true就會顯示
if(req.query.admin === 'true'){
next()
return
}
//其餘顯示沒有權限
res.send("<h2>您沒有權限</h2>")
}
  • 回傳 json
    • res.json({ message: "hello" })
    • 通常畫面會搭配 vue,所以.send()可以改為回傳資料
1
2
3
4
5
6
7
8
9
10
11
12
13
app.get('/users', auth, (req, res) => {
// res.send("<h1>Users List</h1>")
res.json({ message: "使用者清單" })
})

function auth(req, res, next) {
if(req.query.admin === 'true'){
next()
return
}
// res.send("<h2>您沒有權限</h2>")
res.json({ message: "您沒有權限" })
}

專案結構化

  • 在專案中新增 src 資料夾
  • 在 src 中新增 routes 與 middlewares 資料夾
    • 將 index.js 中的 middlewares 跟 routes 拆到資料夾中
      • 最後加 module.exports = middleware名稱

logger

1
2
3
4
5
6
7
8
9
10
// 路徑:middlewares/logger.js

// 處理 log 的 middleware
function logger(req, res, next) {
console.log("log")
next()
}

// export 出去
module.exports = logger

router

  • 引入 express,從 express 拿出 Router()
  • 將之前的 app 改為 router
    • 有用到 middleware 則需要用 require("檔案路徑") 引入
      • const auth = require("../middlewares/auth.js")
  • 最後加 module.exports = router
1
2
3
4
5
6
7
8
9
const express = require("express")
const router = express.Router()

router.get('/', (req, res) => {
let time = new Date()
res.json({ message: "首頁", visit_time: time.toLocaleString() })
})

module.exports = router

index.js

  • 引入所有建立好的 router 跟 middlewares
  • use 他們
1
2
3
4
5
6
7
8
9
10
11
12
13
const express = require('express')
const app = express()
const indexRouter = require("./src/routes/index.js")
const productsRouter = require("./src/routes/products.js")
const usersRouter = require("./src/routes/users.js")
const logger = require("./src/middlewares/logger.js")

app.use(logger)
app.use(indexRouter)
app.use(productsRouter)
app.use(usersRouter)

app.listen(3200)