Best Practices for Structuring Node.js Projects

Learn how to organize your Node.js application files and directories for better maintainability and scalability.

0 likes
3 views

Rule Content

{
  "title": "Best Practices for Structuring Node.js Projects",
  "description": "Learn how to organize your Node.js application files and directories for better maintainability and scalability.",
  "category": "Node.js Cursor Rules",
  "rules": [
    {
      "name": "Organize Code by Feature",
      "description": "Structure your project by grouping related files (models, controllers, routes) within feature-specific directories to enhance modularity and maintainability.",
      "recommendation": "Adopt a feature-based directory structure where each feature has its own folder containing all related components.",
      "example": {
        "before": "├── controllers/\n├── models/\n├── routes/\n├── services/\n└── utils/",
        "after": "├── user/\n│   ├── userController.js\n│   ├── userModel.js\n│   ├── userRoutes.js\n│   └── userService.js\n├── product/\n│   ├── productController.js\n│   ├── productModel.js\n│   ├── productRoutes.js\n│   └── productService.js\n└── utils/"
      }
    },
    {
      "name": "Separate Configuration Files",
      "description": "Store configuration settings in dedicated files or environment variables to manage different environments and enhance security.",
      "recommendation": "Use a 'config' directory to house environment-specific configuration files and utilize environment variables for sensitive information.",
      "example": {
        "before": "const dbHost = 'localhost';\nconst dbUser = 'root';\nconst dbPass = 'password';",
        "after": "// .env\nDB_HOST=localhost\nDB_USER=root\nDB_PASS=password\n\n// config/database.js\nrequire('dotenv').config();\nmodule.exports = {\n  host: process.env.DB_HOST,\n  user: process.env.DB_USER,\n  pass: process.env.DB_PASS,\n};"
      }
    },
    {
      "name": "Implement Middleware Separately",
      "description": "Organize middleware functions in a dedicated directory to promote reusability and maintainability.",
      "recommendation": "Create a 'middleware' directory to store all middleware functions, each handling a specific responsibility.",
      "example": {
        "before": "app.use((req, res, next) => {\n  // Authentication logic\n  next();\n});\napp.use((req, res, next) => {\n  // Logging logic\n  next();\n});",
        "after": "// middleware/auth.js\nmodule.exports = (req, res, next) => {\n  // Authentication logic\n  next();\n};\n\n// middleware/logger.js\nmodule.exports = (req, res, next) => {\n  // Logging logic\n  next();\n};\n\n// app.js\nconst auth = require('./middleware/auth');\nconst logger = require('./middleware/logger');\napp.use(auth);\napp.use(logger);"
      }
    },
    {
      "name": "Use Asynchronous Code",
      "description": "Utilize asynchronous programming patterns to improve performance and scalability.",
      "recommendation": "Employ async/await syntax for handling asynchronous operations to avoid callback hell and enhance code readability.",
      "example": {
        "before": "function getData() {\n  fetchData1((err, data1) => {\n    if (err) return handleError(err);\n    fetchData2(data1, (err, data2) => {\n      if (err) return handleError(err);\n      fetchData3(data2, (err, data3) => {\n        if (err) return handleError(err);\n        processData(data3);\n      });\n    });\n  });\n}",
        "after": "async function getData() {\n  try {\n    const data1 = await fetchData1();\n    const data2 = await fetchData2(data1);\n    const data3 = await fetchData3(data2);\n    processData(data3);\n  } catch (err) {\n    handleError(err);\n  }\n}"
      }
    },
    {
      "name": "Maintain Consistent Naming Conventions",
      "description": "Use consistent and meaningful naming conventions for files and directories to improve code readability and maintainability.",
      "recommendation": "Adopt a naming convention such as kebab-case for directories and camelCase for files, and apply it consistently throughout the project.",
      "example": {
        "before": "├── UserServices/\n│   ├── userController.js\n│   ├── user_model.js\n│   └── user-routes.js",
        "after": "├── user-services/\n│   ├── userController.js\n│   ├── userModel.js\n│   └── userRoutes.js"
      }
    }
  ]
}