セットアップ
サーバーの作成と起動
const express = require("express"); const app = express(); app.listen(3000, () => console.log("Running on :3000"));
組み込みミドルウェア
app.use(express.json()); // JSON ボディをパース app.use(express.urlencoded({ extended: true })); // フォームデータ app.use(express.static("public")); // 静的ファイルを提供
ルーティング
HTTP メソッド
app.get("/users", (req, res) => res.json(users)); app.post("/users", (req, res) => res.status(201).json(req.body)); app.put("/users/:id", (req, res) => res.json(updated)); app.delete("/users/:id", (req, res) => res.sendStatus(204));
ルートパラメーター
app.get("/users/:id", (req, res) => { const { id } = req.params; res.json({ id }); });
クエリ文字列
// GET /search?q=express&page=2 app.get("/search", (req, res) => { const { q, page } = req.query; res.json({ q, page }); });
ミドルウェア
アプリケーションレベル
app.use((req, res, next) => { console.log(`${req.method} ${req.url}`); next(); });
ルートレベル
const auth = (req, res, next) => { if (!req.headers.authorization) return res.sendStatus(401); next(); }; app.get("/secret", auth, (req, res) => res.json({ ok: true }));
実行順序
app.use(fn)すべてのリクエストで実行(順番に)
app.use(path, fn)一致するパスプレフィックスのみで実行
next()次のミドルウェアに制御を渡す
next(err)エラーハンドラーにスキップ
リクエストとレスポンス
リクエストオブジェクト
req.paramsルートパラメーター(/users/:id
req.queryクエリ文字列(?key=val
req.bodyパース済みリクエストボディ(パーサー必要)
req.headersリクエストヘッダーオブジェクト
req.methodHTTP メソッド(GET、POST など)
req.pathURL パス名
req.cookiesCookie(cookie-parser 必要)
レスポンスオブジェクト
res.json(obj)JSON レスポンスを送信
res.send(body)文字列/Buffer/オブジェクトを送信
res.status(code)HTTP ステータスを設定(チェーン可)
res.redirect(url)302 リダイレクト(ステータスも指定可)
res.sendFile(path)ファイルをレスポンスとして送信
res.sendStatus(code)デフォルトテキスト付きでステータスを送信
res.set(header, val)レスポンスヘッダーを設定
エラーハンドリング
エラーミドルウェア
// 4つのパラメーターが必要 — Express がエラーハンドラーと認識 app.use((err, req, res, next) => { console.error(err.stack); res.status(err.status || 500).json({ error: err.message }); });

他のすべての app.use() とルートの後に定義する

非同期エラー
// 非同期ルートハンドラーを包んで拒否をキャッチ const wrap = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next); app.get("/data", wrap(async (req, res) => { const data = await fetchData(); res.json(data); }));
静的ファイル
静的ディレクトリを提供
app.use(express.static("public")); // public/style.css を /style.css で提供 // 仮想パスプレフィックス付き app.use("/assets", express.static("public")); // public/style.css を /assets/style.css で提供
オプション
dotfiles'ignore' | 'allow' | 'deny'
maxAgeCache-Control max-age(ミリ秒)
indexインデックスファイル名(デフォルト: index.html
fallthrough404 時に次のミドルウェアに渡す
テンプレート
ビューエンジンのセットアップ
app.set("view engine", "ejs"); app.set("views", "./views"); app.get("/", (req, res) => { res.render("index", { title: "Home", items: [1, 2, 3] }); });
よく使うエンジン
ejs埋め込み JS テンプレート(<%= val %>
pugインデントベース(旧 Jade)
handlebarsMustache スタイル({{val}}
ルーター
モジュール化ルート
// routes/users.js const router = require("express").Router(); router.get("/", (req, res) => res.json(users)); router.get("/:id", (req, res) => res.json(user)); module.exports = router;
ルーターをマウント
const usersRouter = require("./routes/users"); app.use("/api/users", usersRouter); // GET /api/users -> ルーターの "/" // GET /api/users/5 -> ルーターの "/:id"
ルーターメソッド
router.get/post/put/deleteHTTP メソッドハンドラー
router.use(fn)ルーターレベルのミドルウェア
router.param(name, fn)ルートパラメーターの前処理
router.route(path)1つのパスでメソッドをチェーン
認証パターン
JWT ミドルウェア
const jwt = require("jsonwebtoken"); const auth = (req, res, next) => { const token = req.headers.authorization?.split(" ")[1]; if (!token) return res.sendStatus(401); req.user = jwt.verify(token, process.env.SECRET); next(); };
保護されたルート
app.get("/profile", auth, (req, res) => { res.json({ user: req.user }); }); app.use("/api/admin", auth, adminRouter);
よくあるパターン
CORS
const cors = require("cors"); app.use(cors()); // すべてのオリジンを許可 app.use(cors({ origin: "https://example.com" })); // 制限
環境設定
const port = process.env.PORT || 3000; app.listen(port); // ルートで環境変数にアクセス if (app.get("env") === "production") { app.use(helmet()); }
便利な npm パッケージ
corsクロスオリジンリソース共有
helmetセキュリティヘッダー
morganHTTP リクエストロガー
cookie-parserCookie ヘッダーをパース
dotenv.envprocess.env に読み込む
multerマルチパートフォームデータ(ファイルアップロード)