MongoDBNode.js

express.Routerを使ってルート定義を分割する

はじめに

前回、単純なルーティング定義をapp.jsに詰め込んだが、app.jsのコードが肥大化してきているので、 express.Router を使って、ルーティング定義を分割してみる。

express.Routerを使うメリットは以下がありそう。

  1. コードの整理
    ルーティング定義をモジュールに分割できるので、コードを整理できる。
  2. ミドルウェアの適用
    特定のルートに対して、任意の処理を挟み込むことが可能。
  3. ルートプレフィックス
    ルートプレフィックス(URLの先頭部分)を指定できる。
  4. 可読性
    特定の機能やリソースに関連するルートをまとめることで可読性があがる。

express.Router

Routerモジュールの作成

まずルートモジュールをまとめるrouters フォルダをプロジェクト直下に作成する。

次にusersコレクション用のルートをまとめるためのusersRoutes.js を作成する。

usersRoutes.jsにルータオブジェクト作成、ルート定義とミドルウェアの設定を行う。

ルータオブジェクト作成

const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");

モデル定義

const Schema = mongoose.Schema;
const userSchema = new Schema(
  {
    name: String,
    age: Number,
  },
  { timestamps: true }
);

ミドルウェア設定

router.use((req, res, next) => {
  console.log("Time: ", Date.now());
  next();
});

ルート定義

// READ
// 全件取得
router.get("/users", async (req, res) => {
  try {
    const users = await User.find();
    res.json(users);
  } catch (error) {
    res.status(500).json({ error: "ユーザの取得に失敗しました。" });
  }
});

// IDでユーザを絞りこみ
router.get("/users/:userId", async (req, res) => {
  try {
    const userId = req.params.userId;
    const user = await User.findById(userId);
    res.json(user);
  } catch (error) {
    res.status(500).json({ error: "ユーザの取得に失敗しました。" });
  }
});

// CREATE
router.post("/users", async (req, res) => {
  try {
    const addUser = req.body;
    const newUser = new User(addUser);
    await newUser.save();

    res.json({ message: "ユーザが登録されました。", user: newUser });
  } catch (error) {
    res.status(500).json({ error: "ユーザの登録に失敗しました。" });
  }
});

// UPDATE
router.patch("/users/:userId", async (req, res) => {
  try {
    const userId = req.params.userId;
    const updateFields = req.body;

    // ユーザを更新
    const updatedUser = await User.findByIdAndUpdate(
      userId,
      { $set: updateFields },
      { new: true }
    );
    if (!updatedUser) {
      return res.status(404).json({ message: "ユーザが見つかりません。" });
    }

    res.json({ message: "ユーザが更新されました。", user: updatedUser });
  } catch (error) {
    res.status(500).json({ error: "ユーザの更新に失敗しました。" });
  }
});

// DELETE
router.delete("/users/:userId", async (req, res) => {
  try {
    const userId = req.params.userId;
    const deletedUser = await User.findByIdAndDelete(userId);

    if (!deletedUser) {
      return res.status(404).json({ message: "ユーザが見つかりません。" });
    }

    res.json({ message: "ユーザが削除されました。", user: deletedUser });
  } catch (error) {
    res.status(500).json({ error: "ユーザの削除に失敗しました。" });
  }
});

モジュールエクスポート

module.exports = router;

ルータモジュールをアプリケーションにロード

app.js でルータモジュールをロードする。

const userRoutes = require("./routes/usersRoutes");
app.use(userRoutes);

ルートプレフィックスに /api をつければ、http://localhost:3000/api/users にエンドポイントが作成される。

const userRoutes = require("./routes/usersRoutes");
app.use("/api", userRoutes);

ソースコード

今回作ったプロジェクトは次のGithubで管理

GitHub - ashitaka1963/express_connect_mongodb_sample at f9e13f181e94cdeed9658da27be8fe4a99e42bc8

おわりに

無事にexpress.Routerを使いコード分割を行うことができた。

いまは、MongoDBのユーザコレクションのリソースに対するモジュール分割だけだが、リソースが増えればより効果が出てきそう。

ただ、まだ分割したモジュール内にMongoDB関連のコードが丸っと入っているので、次はこのあたりを整理していく。

参考

Express でのルーティング