---
title: 後端環境相關
tags: [環境相關]
---
# 後端環境相關
> 主要採用 JavaScript,並補充 TypeScript 專案的建構方式
## 後端建立環境指令與順序
1. 🧰 專案初始化與安裝流程
2. ⚙️ 開發用指令(scripts)
3. 📌 需手動建立的檔案建議(.env、結構)
📁 推測的檔案內容依據:
- 框架:Express
- 驗證系統:Passport(local + jwt)
- 資料庫:MongoDB(Mongoose)
- 加密:bcrypt
- 環境變數:dotenv
- 開發工具:nodemon + eslint + prettier
## 🧾 整體安裝清單懶人表(依順序)
| 類別 | 套件 | 安裝指令 |
| ------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| 建立環境 | `express dotenv` | `npm install express dotenv` |
| 建立環境(開發用) | `nodemon eslint ...` | `npm install -D nodemon eslint @eslint/js eslint-config-prettier eslint-plugin-prettier globals` |
| 常駐工具 | `cors http-status-codes validator` | `npm install cors http-status-codes validator` |
| 功能型功能 | `bcrypt jsonwebtoken mongoose passport passport-local passport-jwt` | `npm install bcrypt jsonwebtoken mongoose passport passport-local passport-jwt` |
---
# 🧰 專案初始化與安裝流程
## 💿 進入專案資料夾裡面放後端的區域
```
cd back
```
---
## 1️⃣ 建立環境(系統框架與開發基礎)
> 📌 目的:讓 Express 專案可以跑起來、有伺服器、有環境變數、能熱重啟、能檢查語法
### 📍 初始化 Node 專案
```
npm init --yes
npm i -D nodemon
```
#### 📝 改動 packge.json
設定為 module 語法
```
"type": "module",
```
設定開發用指令(scripts)
```
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "nodemon index.js",
"start": "node index.js"
},
```
### 📍 安裝框架與環境變數工具
```
npm i express dotenv
```
### 📌 需手動建立的檔案建議(.env、.gitignore)
#### 📝 建立檔案.env
> 內容為:環境變數等不能說的秘密
檔名
```
.env
```
#### 📝 建立檔案.gitignore
> 內容為:要設定讓 git 忽略的檔案
檔名
```
.gitignore
```
內容(最少)
```
.env
node_modules
dump/*
!dump/.gitkeep
```
#### 📁 建立資料夾 models
> 內容:定義資料庫的資料結構(Schema)、驗證規則與資料模型
```
models
```
**用途說明**:
- 定義資料表/集合的欄位結構與資料型態
- 設定欄位驗證規則(必填、長度、格式等)
- 定義資料模型的方法(如密碼加密、資料查詢等)
**常見檔案範例**:
- `user.js`:使用者資料模型
- `product.js`:商品資料模型
- `order.js`:訂單資料模型
**Mongoose 範例**:
```js
import { Schema, model } from "mongoose";
const userSchema = new Schema({
account: { type: String, required: true, unique: true },
email: { type: String, required: true },
password: { type: String, required: true },
});
export default model("users", userSchema);
```
#### 📁 建立資料夾 controllers
> 內容:處理業務邏輯,對資料庫執行增刪改查(CRUD)操作
```
controllers
```
**用途說明**:
- 接收路由傳來的請求資料
- 呼叫 models 進行資料庫操作
- 處理資料處理邏輯與錯誤處理
- 回傳處理結果給前端
**常見檔案範例**:
- `userController.js`:處理使用者相關操作(註冊、登入、更新資料等)
- `productController.js`:處理商品相關操作(新增、查詢、修改、刪除)
- `orderController.js`:處理訂單相關操作
**Controller 範例**:
```js
import User from "../models/user.js";
import { StatusCodes } from "http-status-codes";
export const register = async (req, res) => {
try {
await User.create(req.body);
res.status(StatusCodes.OK).json({ success: true, message: "註冊成功" });
} catch (error) {
res
.status(StatusCodes.INTERNAL_SERVER_ERROR)
.json({ success: false, message: "註冊失敗" });
}
};
```
#### 📁 建立資料夾 middlewares
> 內容:處理請求前後的中介邏輯,如身分驗證、資料驗證、錯誤處理等
```
middlewares
```
**用途說明**:
- **身分驗證**:檢查使用者是否登入、token 是否有效
- **權限控制**:檢查使用者是否有權限執行某操作
- **資料驗證**:驗證請求資料格式是否正確
- **錯誤處理**:統一處理錯誤回應格式
**常見檔案範例**:
- `auth.js`:身分驗證中介軟體(如 JWT 驗證)
- `validator.js`:資料驗證中介軟體
- `errorHandler.js`:錯誤處理中介軟體
- `upload.js`:檔案上傳處理中介軟體
**Middleware 範例**:
```js
import passport from "passport";
import { StatusCodes } from "http-status-codes";
// JWT 驗證中介軟體
export const auth = (req, res, next) => {
passport.authenticate("jwt", { session: false }, (error, user, info) => {
if (error || !user) {
return res
.status(StatusCodes.UNAUTHORIZED)
.json({ success: false, message: "未登入" });
}
req.user = user;
next();
})(req, res, next);
};
```
#### 📁 建立資料夾 routers
> 內容:定義 API 路由規則,將請求分配給對應的 controller
```
routers
```
**用途說明**:
- 定義 API 端點路徑(如 `/api/users`, `/api/products`)
- 指定 HTTP 方法(GET, POST, PUT, DELETE)
- 串接 middlewares 與 controllers
- 組織與管理 API 結構
**常見檔案範例**:
- `userRouter.js`:使用者相關路由(註冊、登入、個人資料)
- `productRouter.js`:商品相關路由
- `orderRouter.js`:訂單相關路由
**Router 範例**:
```js
import { Router } from "express";
import { register, login, getProfile } from "../controllers/userController.js";
import { auth } from "../middlewares/auth.js";
const router = Router();
router.post("/register", register);
router.post("/login", login);
router.get("/profile", auth, getProfile); // 需要驗證身分
export default router;
```
**在 index.js 中使用**:
```js
import userRouter from "./routers/userRouter.js";
app.use("/api/users", userRouter);
```
#### 📝 建立檔案 index.js
檔名
```
index.js
```
> 內容:
```js
import "dotenv/config";
import express from "express";
import mongoose from "mongoose";
import { StatusCodes } from "http-status-codes";
import cors from "cors";
// routes(根據不同專案有不同的東西)
// import 路由名稱 from '路由檔案'
// passport.js
import "./passport.js";
// 連線資料庫 1.設環境變數 2.成功 3.失敗
mongoose
.connect(process.env.DB_URL)
.then(() => {
console.log("☑️ 資料庫連接成功");
mongoose.set("sanitizeFilter", true);
})
.catch((err) => {
console.log("⛔ 資料庫連線失敗");
console.error("資料庫連線失敗", err);
});
// 建立 express 伺服器
const app = express();
app.use(express.json());
// 使用 CORS 中介軟體(處理跨域請求)
app.use(cors());
// ↓錯誤處理
app.use((err, req, res, _next) => {
res.status(StatusCodes.BAD_REQUEST).json({
sucess: false,
message: "Json格式錯誤",
});
});
// 設置路由(根據不同專案有不同的東西)
// app.use('/路由檔案', 路由名稱)
// 處理未定義的路由
app.all(/.*/, (req, res) => {
res.status(StatusCodes.NOT_FOUND).json({
success: false,
message: "找不到該路由",
});
});
// 監聽與啟動
app.listen(4000, () => {
console.log("伺服器啟動");
});
```
### 📍 安裝開發用工具(語法檢查、自動重啟)
> 檢查語法是否符合規則(eslint / oslint / tslint…)
> 檔案變動時自動重啟伺服器(開發用)
```
npm init @eslint/config@latest
```
```
npm i -D nodemon prettier eslint-plugin-prettier eslint-config-prettier
```
#### 📝 eslint.config.js 內容
檔名
```
eslint.config.js
```
檔案內容
```
import js from '@eslint/js'
import globals from 'globals'
import { defineConfig } from 'eslint/config'
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
export default defineConfig([
{
files: ['**/*.{js,mjs,cjs}'],
plugins: { js },
extends: ['js/recommended'],
},
{ files: ['**/*.{js,mjs,cjs}'], languageOptions: { globals: globals.node } },
eslintPluginPrettierRecommended,
{
rules: {
'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
},
},
])
```
#### 📝 .prettierrc.json 內容
檔名
```
.prettierrc.json
```
檔案內容
```
{
"$schema": "https://json.schemastore.org/prettierrc",
"printWidth": 100,
"semi": false,
"singleQuote": true
}
```
> 補充:index.js 是進入點
---
## 2️⃣ 常駐工具型功能(必裝輔助開發用,不是主流程但超常出現)
> 📌 目的:提升錯誤處理與 API 品質,跨域通訊、欄位驗證也能幫忙
```
npm i cors http-status-codes validator
```
1. cors:讓前端能 call API(跨網域)
2. http-status-codes:不要手寫 404、200 之類的數字
3. validator:欄位驗證(ex: email、長度)
---
## 3️⃣ 明確功能型功能(安裝你需要用的功能套件,依需求增減)
> 📌 目的:實作帳號登入、密碼加密、token 機制、資料庫操作,依需求增減
資料庫:MongoDB
```
npm i mongoose
```
mongoose:操作 MongoDB
各種驗證
```
npm i bcrypt jsonwebtoken mongoose passport passport-local passport-jwt
```
1. bcrypt:密碼加密與比對
2. jsonwebtoken:產出 JWT token
3. passport:登入驗證框架
4. passport-local:帳號密碼策略
5. passport-jwt:JWT 身分驗證策略
## 4️⃣ (選用)使用 TypeScript
> 📌 目的:提升開發體驗、型別安全、減少執行時錯誤
### 📍 安裝 TypeScript 相關套件
```bash
npm install -D typescript @types/node @types/express ts-node
npm install -D @types/cors @types/bcrypt @types/jsonwebtoken @types/validator
npm install -D @types/passport @types/passport-local @types/passport-jwt
```
**套件說明**:
| 套件 | 用途 |
| ----------------------- | -------------------------------- |
| `typescript` | TypeScript 編譯器 |
| `@types/node` | Node.js 型別定義 |
| `@types/express` | Express 型別定義 |
| `ts-node` | 直接執行 TypeScript 檔案(開發用) |
| `@types/cors` | CORS 套件型別定義 |
| `@types/bcrypt` | bcrypt 套件型別定義 |
| `@types/jsonwebtoken` | JWT 套件型別定義 |
| `@types/validator` | validator 套件型別定義 |
| `@types/passport` | Passport 主套件型別定義 |
| `@types/passport-local` | Passport Local 策略型別定義 |
| `@types/passport-jwt` | Passport JWT 策略型別定義 |
### 📝 建立 tsconfig.json
檔名:
```
tsconfig.json
```
內容:
```json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "node",
"outDir": "./dist",
"rootDir": "./",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"types": ["node"]
},
"include": ["**/*.ts"],
"exclude": ["node_modules", "dist"]
}
```
**設定說明**:
- `target`: 編譯後的 JavaScript 版本
- `module`: 模組系統(使用 ESNext 支援 ES Modules)
- `outDir`: 編譯後的檔案輸出資料夾
- `strict`: 啟用所有嚴格型別檢查
- `esModuleInterop`: 改善 CommonJS 與 ES Module 互通性
### 📝 調整 package.json
將 scripts 區塊修改為:
```json
{
"type": "module",
"scripts": {
"dev": "nodemon --exec ts-node index.ts",
"build": "tsc",
"start": "node dist/index.js",
"type-check": "tsc --noEmit"
}
}
```
**指令說明**:
- `npm run dev`: 開發模式,使用 ts-node 直接執行 TypeScript
- `npm run build`: 編譯 TypeScript 為 JavaScript
- `npm start`: 執行編譯後的 JavaScript(正式環境)
- `npm run type-check`: 只檢查型別,不編譯
### 📝 調整 ESLint 設定
安裝 TypeScript ESLint 套件:
```bash
npm install -D typescript-eslint
```
修改 `eslint.config.js`:
```js
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
import { defineConfig } from "eslint/config";
export default defineConfig(
js.configs.recommended,
tseslint.configs.recommended,
{
files: ["**/*.{js,mjs,cjs,ts}"],
languageOptions: {
globals: globals.node,
},
},
{
files: ["**/*.ts"],
rules: {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"warn",
{ argsIgnorePattern: "^_" },
],
},
},
eslintPluginPrettierRecommended
);
```
### 📁 檔案結構調整
將原本的 `.js` 檔案改為 `.ts`:
```
專案根目錄/
├── index.ts (原 index.js)
├── passport.ts (原 passport.js)
├── models/
│ └── user.ts (原 user.js)
├── controllers/
│ └── userController.ts
├── middlewares/
│ └── auth.ts
├── routers/
│ └── userRouter.ts
└── dist/ (編譯後的輸出資料夾)
```
### 📝 TypeScript 範例:User Model
```ts
import { Schema, model, Document } from "mongoose";
// 定義介面
export interface IUser extends Document {
account: string;
email: string;
password: string;
}
// 定義 Schema
const userSchema = new Schema<IUser>({
account: { type: String, required: true, unique: true },
email: { type: String, required: true },
password: { type: String, required: true },
});
// 匯出模型
export default model<IUser>("users", userSchema);
```
### 📝 TypeScript 範例:Controller
```ts
import { Request, Response } from "express";
import User from "../models/user.js";
import { StatusCodes } from "http-status-codes";
export const register = async (req: Request, res: Response): Promise<void> => {
try {
await User.create(req.body);
res.status(StatusCodes.OK).json({ success: true, message: "註冊成功" });
} catch (error) {
res
.status(StatusCodes.INTERNAL_SERVER_ERROR)
.json({ success: false, message: "註冊失敗" });
}
};
```
### 📝 TypeScript 範例:index.ts
```ts
import "dotenv/config";
import express, { Request, Response, NextFunction } from "express";
import mongoose from "mongoose";
import { StatusCodes } from "http-status-codes";
import cors from "cors";
// routes
// import userRouter from './routers/userRouter.js'
// passport.js
import "./passport.js";
// 連線資料庫
mongoose
.connect(process.env.DB_URL as string)
.then(() => {
console.log("☑️ 資料庫連接成功");
mongoose.set("sanitizeFilter", true);
})
.catch((err) => {
console.log("⛔ 資料庫連線失敗");
console.error("資料庫連線失敗", err);
});
// 建立 express 伺服器
const app = express();
app.use(express.json());
// 使用 CORS
app.use(cors());
// 錯誤處理
app.use((err: Error, req: Request, res: Response, _next: NextFunction) => {
res.status(StatusCodes.BAD_REQUEST).json({
success: false,
message: "Json格式錯誤",
});
});
// 設置路由
// app.use('/api/users', userRouter)
// 處理未定義的路由
app.all(/.*/, (req: Request, res: Response) => {
res.status(StatusCodes.NOT_FOUND).json({
success: false,
message: "找不到該路由",
});
});
// 監聽與啟動
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => {
console.log(`伺服器啟動於 port ${PORT}`);
});
```
### ⚠️ 注意事項
1. **import 路徑需加 .js 副檔名**(即使是 TypeScript 檔案)
```ts
import User from "../models/user.js"; // ✅ 正確
import User from "../models/user"; // ❌ 可能出錯
```
2. **型別定義不完整時的處理**
```ts
// 如果某個套件沒有 @types,可以建立 types/custom.d.ts
declare module "some-package";
```
3. **環境變數型別安全**
```ts
// 可以建立 types/env.d.ts
declare global {
namespace NodeJS {
interface ProcessEnv {
DB_URL: string;
JWT_SECRET: string;
PORT?: string;
}
}
}
export {};
```
### 🎯 TypeScript vs JavaScript 決策
| 情境 | 建議 |
| -------------------------- | ------------- |
| 小型專案、快速開發 | JavaScript |
| 多人協作、大型專案 | TypeScript ✅ |
| 需要高度型別安全 | TypeScript ✅ |
| 學習成本考量 | JavaScript |
| 與前端 TypeScript 專案整合 | TypeScript ✅ |
---
# 🧩 後端套件分類表(含 `dependencies` 與 `devDependencies`)
| 套件名稱 | 安裝位置 | 類型 | 用途說明 | 代表常見用途 |
| ---------------------------- | -------- | -------- | ------------------- | ---------------------------- |
| `express` | ✅ 後端 | Web 框架 | 架設 API Server | 處理請求與回應 |
| `dotenv` | ✅ 後端 | 設定工具 | 管理 `.env` 變數 | API 金鑰 |
| `nodemon` | ✅ 後端 | 開發工具 | 變更自動重啟 server | 提升開發效率 |
| `cors` | ✅ 後端 | 中介軟體 | 解決跨域問題 | 前後端分離 |
| `body-parser` | ✅ 後端 | 請求解析 | 拿到 req.body | POST/PUT 資料 |
| `jsonwebtoken` | ✅ 後端 | 驗證 | 處理 JWT 驗證 | 登入憑證 |
| `bcryptjs` / `bcrypt` | ✅ 後端 | 加密 | 密碼加密比對 | 登入系統 |
| `mongoose` / `mysql2` / `pg` | ✅ 後端 | DB 驅動 | 資料庫連線操作 | MongoDB / MySQL / PostgreSQL |
| `multer` | ✅ 後端 | 檔案處理 | 處理檔案上傳 | 上傳圖片 |
## 📁 一、建立環境款(系統框架與開發支援)
| 套件名 | 用途說明 | 適合場景 |
| --------------------------------------------------- | ------------------------------------------------------ | ----------------------------------- |
| `express` | 建立 HTTP 伺服器與路由管理,是整個後端的基礎 | 所有 Express 專案必備 |
| `dotenv` | 讀取 `.env` 檔案設定環境變數 | 區分開發、正式環境設定(如 DB URI) |
| `nodemon` | 檔案變動時自動重啟伺服器(開發用) | 提高開發效率,不需手動重啟 |
| `eslint` / `@eslint/js` | 程式碼風格檢查器(靜態分析) | 寫 code 時維持一致風格 |
| `eslint-config-prettier` / `eslint-plugin-prettier` | 整合 Prettier 與 ESLint,避免衝突 | 同時使用兩者時很常用 |
| `globals` | 提供 ESLint 可辨識的全域變數(如 `window`, `process`) | 靜態檢查時避免誤報錯誤 |
---
## 🛠️ 二、常駐工具型功能款(幾乎每個專案會加的功能輔助)
| 套件名 | 用途說明 | 適合場景 |
| ------------------- | ------------------------------------------ | ---------------------- |
| `cors` | 處理跨來源請求,允許前端與後端不同來源通訊 | 前後端分離開發中必裝 |
| `http-status-codes` | 提供標準 HTTP 狀態碼常數,避免寫死數字 | 統一錯誤回應格式 |
| `validator` | 驗證 email、網址、字串格式等(輕量、常用) | 表單驗證、後端欄位檢查 |
---
## 🎯 三、明確功能型功能款(為了特定需求裝的)
| 套件名 | 用途說明 | 適合場景 |
| ---------------- | ----------------------------------- | ----------------------------- |
| `bcrypt` | 加密密碼、驗證密碼 | 帳號登入系統、保護使用者資料 |
| `jsonwebtoken` | 產生與驗證 JWT(token 機制) | 登入後產出 token、驗證使用者 |
| `mongoose` | 操作 MongoDB 的 ODM(資料模型管理) | 資料庫存取、欄位定義與驗證 |
| `passport` | 使用者驗證中介系統 | 處理登入、登出、身分驗證 |
| `passport-local` | `passport` 的本地帳密登入策略 | 基本帳號密碼登入 |
| `passport-jwt` | `passport` 的 JWT 驗證策略 | 支援使用 JWT token 登入持久化 |
---
# 👀 無用的知識增加了
## 各種驗證套件差別
### ✅ 一、**前端送表單前要檢查資料對不對**
> ➤ 負責人:`validator`
🧪 格式錯誤例子:
- Email 不合法
- 密碼太短
- 名稱為空
```js
validator.isEmail(email); // ✅ or ❌
```
### ✅ 二、**登入時要比對使用者密碼**
> ➤ 負責人:`bcrypt`
🔐 一進資料庫前就加密,登入時也用它來比對:
```js
bcrypt.compare(使用者輸入的密碼, 資料庫的加密密碼);
```
### ✅ 三、**登入成功後,要頒發「通關憑證」**
> ➤ 負責人:`jsonwebtoken`
🎫 就像辦完護照拿到簽證,使用者登入成功後,產生一張 **JWT token**。
```js
const token = jwt.sign(payload, secretKey, { expiresIn: "1h" });
```
### ✅ 四、**之後每次請求,要驗證使用者憑證是否合法**
> ➤ 負責人:`passport` + `passport-jwt`
🕵️ 守門系統來了,這邊會攔截請求,看 token 是否正確(如:有沒有過期?有沒有被竄改?)
```js
passport.use(new JwtStrategy(...))
```
### ✅ 五、**第一次登入的帳號密碼邏輯**
> ➤ 負責人:`passport-local`
👮 檢查帳號密碼正確性(第一次登入用的驗證策略)
```js
passport.use(new LocalStrategy(帳號密碼檢查邏輯));
```
---
### 📌 小整理圖:
```
🔎 表單送出前 —— validator
🔐 密碼上路前 —— bcrypt(加密儲存)
✅ 登入成功時 —— jsonwebtoken(產出 token)
🧠 架構整合者 —— passport
└─ passport-local:帳密比對邏輯(登入那刻)
└─ passport-jwt:驗證 JWT token(後續請求)
```
---
### 總整理
| 套件 | 分類 | 簡單比喻 | 驗證什麼? |
| ---------------------- | -------------- | -------------------- | -------------------------- |
| `validator` | 格式驗證 | 格式小警察 | email 格式、必填欄位、長度 |
| `bcrypt` | 加密驗證 | 把密碼攪爛後存起來 | 使用者輸入密碼對不對 |
| `jsonwebtoken` (`jwt`) | 身分憑證 | 成功登入後發的票 | JWT 有效嗎?是誰? |
| `passport` | 驗證系統架構 | 驗證流程主控中心 | 調度各種驗證方式 |
| `passport-local` | 登入策略 | 傳統帳號密碼比對方式 | 使用者帳號密碼是否正確 |
| `passport-jwt` | token 驗證策略 | 持票者是否合法 | JWT 是否有效、是否過期 |
## validator 為什麼是常駐工具?
### 🧪 validator 屬於「常駐工具型功能」的理由
✅ 1. 它不是為了某個功能而來,而是「幫你寫任何功能時更安全」
你寫會員系統會用 validator(驗證 email)
你寫商品系統也會用(名稱長度限制)
寫留言表單、報名表單、客服系統……都用得到
> 它的角色是「資料的守門員」,而不是「功能的實作者」
### ✅ 2. 範圍極廣,不只登入/註冊才用
不像:
passport = 為了登入驗證設計
bcrypt = 為了密碼比對設計
jwt = 為了登入產出 token
這三個是為了「身份驗證」這一個功能而存在,沒做登入就用不到。
但 validator 像是萬用刀:
是你送出任何資料給後端時,都要有人檢查格式
它不是功能,是習慣
### ✅ 3. 你可能根本不做登入,也會用它
例如你只做一個「留言板」,完全匿名:
不需要 passport、bcrypt、jwt
但還是會用 validator → 限制留言內容字數、email 格式、避免空值
| 工具 | 是否功能導向? | 是否常駐? | 分類 |
| ----------------------------- | ------------------------- | ----------------------- | ----------------- |
| `passport` / `bcrypt` / `jwt` | ✅ 明確是為了登入、權限 | ❌ 沒做就不會用 | 🎯 明確功能型功能 |
| `validator` | ❌ 不是某個功能的專屬工具 | ✅ 幾乎什麼功能都能用上 | 🛠 常駐工具型功能 |
---
## 📦 比較各種資料庫對應的套件選擇(給 Node.js 用)
不同資料庫有不同的 Node.js 連接方式與套件選擇。
### 1️⃣ MongoDB
- ✅ 套件:`mongoose`(ODM)
- 功能:提供資料模型、驗證、自動轉換格式等功能
- 📦 替代選項:`mongodb`(原生驅動)→ 比較底層、自由度高但需自己寫邏輯
```
npm i mongoose
```
### 2️⃣ MySQL / MariaDB(關聯式資料庫)
#### 👉 常見套件:
| 套件 | 類型 | 說明 |
| ----------- | ----------- | ------------------------------------------------ |
| `mysql2` | 原生 client | 操作資料庫的最基本工具,查詢語法需自己寫 |
| `sequelize` | ORM | 幫你抽象成「模型」,支援關聯、驗證、migration 等 |
🔧 安裝範例:
```
npm i mysql2 sequelize
```
📘 建議搭配:
- `dotenv`:放 DB 帳密
- `sequelize-cli`(選用):管理 migration、seed 資料
### 3️⃣ PostgreSQL(關聯式,功能強大)
#### 👉 常見套件:
| 套件 | 類型 | 說明 |
| ----------- | ----------- | ----------------------------------------------------- |
| `pg` | 原生 client | 輕量、穩定、官方推薦 |
| `sequelize` | ORM | 也支援 PostgreSQL(多資料庫通用) |
| `prisma` | ORM | 現代化 ORM,更嚴謹、支援 type 安全(TypeScript 友善) |
🔧 安裝範例:
```
npm install pg sequelize
```
或
```
npm install prisma @prisma/client
```
### 4️⃣ SQLite(輕量型,適合測試用)
- 套件:`sqlite3` 或 `better-sqlite3`
- ORM:同樣可以搭配 `sequelize` 或 `prisma`
🔧 安裝範例:
```
npm install sqlite3 sequelize
```
### 5️⃣ 其他(非傳統資料庫)
#### 🧰 Google Sheet × Node.js 的資料存取方式
🎯 **Google Sheet** 的使用邏輯比較不一樣:它不是傳統的資料庫,但可以當作**簡易資料儲存後台**。如果你想在 Node.js 中把 Google Sheet 當作資料來源或儲存工具,這邊有一套常見工具和方式可以用:
✅ 常見用途:
- 表單送出資料 → 存到 Google Sheet
- 後台設定資料 → 存在 Google Sheet 當成資料庫用
- 顯示表格資訊(例如後台管理員表、產品庫存表)
#### 📦 套件選擇與安裝
✅ 最主流方式:使用 Google 官方 API 套件
```
npm i googleapis
```
📁 會用到的東西:
| 工具 | 用途說明 |
| ------------ | --------------------------------------------------- |
| `googleapis` | 官方 SDK,支援 Sheets API(也支援 Drive、Gmail 等) |
| `dotenv` | 儲存你的憑證與 Google Sheet ID |
#### 🗂️ Google Sheet 串接概念流程
1. **在 Google Cloud Platform 建立專案**
2. **啟用 Google Sheets API**
3. **建立服務帳號並下載 JSON 憑證**
4. **與你的 Sheet 分享編輯權給那個服務帳號的 email**
5. **在 Node.js 中使用 `googleapis` 將憑證讀進來、連接 Sheet**
6. **讀取 / 寫入資料**
#### ✅ 套件與初始化步驟懶人表
| 類別 | 套件 | 安裝指令 |
| ---------- | ------------ | ------------------------ |
| 建立環境 | `dotenv` | `npm install dotenv` |
| 功能型功能 | `googleapis` | `npm install googleapis` |
📦 如果你不想處理複雜的授權流程,也可以用 Google 提供的「App Script + Webhook」或用第三方平台如 [SheetDB](https://sheetdb.io/)、[Sheet.best](https://sheet.best/) 這類工具,但彈性較低。
#### 🎯 使用情境與限制提醒
| 優點 | 限制 |
| ------------------------------ | ------------------------------------ |
| 免費、上手快、適合簡單資料儲存 | 不適合大量資料操作(有限 API 限速) |
| 資料可視化、多人共編方便 | 欄位與資料架構不夠嚴謹(不像資料庫) |
| 不用架設 DB 就能快速測試 | 權限管理複雜、容易洩漏憑證 |
#### 🚀 決策建議
| 想要這樣用… | 推薦方案 |
| ------------------------------ | ----------------------------------------- |
| 當成後台可視資料庫(小型系統) | ✅ Google Sheet + `googleapis` |
| 當成表單資料收集庫 | ✅ Google Form + AppScript / `googleapis` |
| 如果日後有複雜關聯查詢 | ❌ 建議改用 MongoDB / MySQL 等真資料庫 |
### 🎯 資料庫懶人決策建議
| 資料庫 | 套件選擇 | 建議用途 |
| --------------- | --------------------------------- | ------------------------------------ |
| MongoDB | `mongoose` | 文件型資料,彈性高,NoSQL 專案首選 |
| MySQL / MariaDB | `mysql2` + `sequelize` | 有資料表設計(欄位明確、關聯明確) |
| PostgreSQL | `pg` + `prisma`(或 `sequelize`) | 關聯型但要更強功能,支援 JSON 欄位等 |
| SQLite | `sqlite3` + `sequelize` | 測試開發、本機 demo 用 |