Хранить код Node.js приложения в пределах одного скрипта и одновременно поддерживать в нем порядок весьма затруднительно. Рассмотрим, как можно грамотно организовать структуру проекта.
Предположим, что имеется приложение, предоставляющее API для оформления заказов на зарегистрированных пользователей, со следующей структурой файлов.
Теперь рассмотрим пример с описанной выше структурой.
constexpress=require('express'),router=express.Router(),UserController=require('../controllers/users.controller'),UsersService=require('../services/users.service');router.use(async(req,res,next)=>{letdata=awaitUsersService.getUsers();if(data){req.users=data;next();}elsereturnres.status(500).send({message:'Error while getting users'});});router.route('/').get(UserController.getUsers).post(UserController.createUser).put(UserController.updateUser).delete(UserController.deleteUser);module.exports=router;
constUsersService=require('../services/users.service');classUsersController{getUsers(req,res){if(req.query.id){if(req.users.hasOwnProperty(req.query.id))returnres.status(200).send({data:req.users[req.query.id],});elsereturnres.status(404).send({message:'User not found.'});}elseif(!req.users)returnres.status(404).send({message:'Users not found.'});returnres.status(200).send({data:req.users});}asynccreateUser(req,res){if(req.body.user&&req.body.user.id){if(req.users.hasOwnProperty(req.body.user.id))returnres.status(409).send({message:'User already exists.',});req.users[req.body.user.id]=req.body.user;letresult=awaitUsersService.createUser(req.users);if(result)returnres.status(200).send(result);elsereturnres.status(500).send({message:'Unable create user.',});}elsereturnres.status(400).send({message:'Bad request.'});}asyncupdateUser(req,res){if(req.body.user&&req.body.user.id){if(!req.users.hasOwnProperty(req.body.user.id))returnres.status(404).send({message:'User not found.'});req.users[req.body.user.id]=req.body.user;letresult=awaitUsersService.updateUser(req.users);if(result)returnres.status(200).send(result);elsereturnres.status(500).send({message:'Unable update user.',});}elsereturnres.status(400).send({message:'Bad request.'});}asyncdeleteUser(req,res){if(req.query.id){if(req.users.hasOwnProperty(req.query.id)){deletereq.users[req.query.id];letresult=awaitUsersService.deleteUser(req.users);if(result)returnres.status(200).send(result);elsereturnres.status(500).send({message:'Unable delete user.',});}elsereturnres.status(404).send({message:'User not found.'});}elsereturnres.status(400).send({message:'Bad request.'});}}module.exports=newUsersController();
В файле app.js содержатся только основные функции промежуточной обработки и функция запуска вашего Node.js приложения.
В директории config находятся файлы для каждой возможной среды окружения, в которой может быть запущено приложение. В такие файлы выносится конфигурация приложения, которая меняется в зависимости от среды запуска.
Директория controllers хранит классы, методы которого выступают обработчиками маршрутов. При этом контроллер создается для каждой взаимосвязанной совокупности маршрутов, например, для всех маршрутов, отвечающих за выполнение действий над заказами.
В services также находятся классы, но их методы отвечают за поставку данных контроллерам, например, с их помощью происходит обращение к базе данных или стороннему API.
В директории routes находятся описания всех маршрутов, причем для любая взаимосвязанная совокупность маршрутов выносится в отдельный файл. Также в routes присутствует файл index.js, который служит для структурированного построения маршрутов. Так, например, с его помощью можно задать префикс маршрутам отдельной группы.
В идеальном варианте у вас всегда должны присутствовать файлы в каждой из директорий controllers, services и routes. Один файл должен описывать самостоятельную логическую часть Node.js приложения.