Как структурировать приложение на ExpressJS? [закрыто]
Проблема с организацией кода в ExpressJS
Я использую веб-фреймворк ExpressJS для NodeJS. Обычно разработчики помещают настройки окружения (разработка, продакшн, тестирование и т.д.) и маршруты в файл app.js
. На мой взгляд, такое решение не совсем удачное, так как для больших приложений файл app.js
становится слишком громоздким.
Я хотел бы организовать свою структуру директорий следующим образом:
| my-application
| -- app.js
| -- config/
| -- environment.js
| -- routes.js
Вот мой код:
app.js
var express = require('express');
var app = module.exports = express.createServer();
require('./config/environment.js')(app, express);
require('./config/routes.js')(app);
app.listen(3000);
config/environment.js
module.exports = function(app, express){
app.configure(function() {
app.use(express.logger());
});
app.configure('development', function() {
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
});
app.configure('production', function() {
app.use(express.errorHandler());
});
};
config/routes.js
module.exports = function(app) {
app.get('/', function(req, res) {
res.send('Hello world !');
});
};
Мой код работает корректно, и, на мой взгляд, структура директорий выглядит аккуратно. Однако мне пришлось адаптировать код, и я не уверен, что изменения действительно улучшили его качество.
Вопрос: является ли моя структура директорий предпочтительнее, чем использование одного файла app.js
, и стоит ли мне прилагать усилия для адаптации кода?
5 ответ(ов)
Вместо экспорта функции или других модулей, мне больше нравится использовать глобальный объект "app". Это позволяет централизованно управлять состоянием и конфигурацией приложения, а также облегчает доступ к другим компонентам. Однако стоит учитывать, что использование глобальных переменных может привести к различным проблемам, например, трудностям с тестированием и поддержкой кода. Если вы все же решите использовать глобальный "app", постарайтесь минимизировать его использование, чтобы избежать потенциальных конфликтов и сделать код более чистым и понятным.
Мой вопрос был задан в апреле 2011 года, и он довольно старый. За это время я смог улучшить свои навыки работы с Express.js и понять, как архитектурировать приложение, написанное с использованием этой библиотеки. Поэтому я делюсь здесь своим опытом.
Вот структура директорий моего приложения:
├── app.js // основной файл
├── config // Конфигурация моего приложения (логгер, глобальные настройки и т.д.)
├── models // Модели данных (например, модель Mongoose)
├── public // Публичный каталог (код на стороне клиента)
├── routes // Определения и реализации маршрутов
├── services // Отдельные сервисы (сервис базы данных, сервис электронной почты и т.д.)
└── views // Шаблоны, которые рендерит сервер для клиента (например, Jade, EJS и т.д.)
App.js
Цель файла app.js
— инициализация приложения на основе Express.js. Он загружает модуль конфигурации, модуль логгирования, ожидает подключения к базе данных и запускает сервер.
'use strict';
require('./config');
var database = require('./services/database');
var express = require('express');
var app = express();
module.exports = app;
function main() {
var http = require('http');
// Конфигурируем приложение.
app.configure(function () {
// ... ... ...
});
app.configure('production', function () {
// ... ... ...
});
app.configure('development', function () {
// ... ... ...
});
var server = http.createServer(app);
// Загружаем все маршруты.
require('./routes')(app);
// Слушаем на http порту.
server.listen(3000);
}
database.connect(function (err) {
if (err) {
// ...
}
main();
});
routes/
В директории маршрутов есть файл index.js
. Его задача — динамически загружать все остальные файлы, находящиеся в директории routes/
. Вот его реализация:
/**
* Этот модуль динамически загружает все модули маршрутов, расположенные в каталоге routes/
*/
'use strict';
var fs = require('fs');
var path = require('path');
module.exports = function (app) {
fs.readdirSync('./routes').forEach(function (file) {
// Избегаем чтения текущего файла.
if (file === path.basename(__filename)) { return; }
// Загружаем файл маршрута.
require('./' + file)(app);
});
};
С помощью этого модуля создание нового определения и реализации маршрута становится очень простым. Например, hello.js
:
function hello(req, res) {
res.send('Hello world');
}
module.exports = function (app) {
app.get('/api/hello_world', hello);
};
Каждый модуль маршрута является независимым.
Я считаю, что это отличный способ реализации. Это не ограничивается только Express, но я замечал довольно много проектов на Node.js на GitHub, которые делают то же самое. Они выносят параметры конфигурации и разбивают меньшие модули (в некоторых случаях каждую URI) на отдельные файлы.
Я бы рекомендовал просмотреть проекты, специфичные для Express, на GitHub, чтобы получить представление. На мой взгляд, тот подход, который вы используете, совершенно верен.
Вы можете использовать следующую структуру папок для ваших веб-приложений на основе MVC. Это эффективный подход для крупных и средних проектов:
myapp
|
|
|____app
| |____controllers
| | |____home.js
| |
| |____models
| | |___home.js
| |
| |____views
| |___404.ejs
| |___error.ejs
| |___index.ejs
| |___login.ejs
| |___signup.ejs
|
|
|_____config
| |___auth.js
| |___constants.js
| |___database.js
| |___passport.js
| |___routes.js
|
|
|____lib
| |___email.js
|
|____node_modules
|
|
|____public.js
| |____css
| | |__style.css
| |
| |____js
| | |__script.js
| |
| |____img
| | |__img.jpg
| |
| |____uploads
| |__img.jpg
|
|
|
|_____app.js
|
|
|
|_____package.json
Я создал npm модуль для генерации структуры папок в формате Express MVC. Вы можете найти его по следующей ссылке: express-mvc-generator.
Вот простые шаги для генерации и использования этого модуля:
- Установите модуль:
npm install express-mvc-generator -g
- Проверьте доступные опции:
express -h
- Генерируйте структуру Express MVC:
express myapp
- Установите зависимости:
npm install
- Откройте файл
config/database.js
, чтобы настроить ваше подключение к MongoDB. - Запустите приложение:
node app
илиnodemon app
- Перейдите по URL:
http://localhost:8042/signup
илиhttp://ваш_IP:8042/signup
Надеюсь, эта информация поможет вам настроить ваше приложение! Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать.
Я не думаю, что добавление маршрутов в конфигурацию — это хороший подход. Лучше использовать такую структуру:
application/
| - app.js
| - config.js
| - public/ (статические файлы - js, css, изображения)
| - views/ (все ваши файлы представлений)
| - libraries/ (это также можно назвать модулями или маршрутами/)
| - users.js
| - products.js
| - и т.д...
Таким образом, файлы products.js и users.js будут содержать все ваши маршруты и всю логику внутри.
Как получить переменные GET (строки запроса) в Express.js на Node.js?
Ошибка: запрос слишком велик
Express.js: app.listen vs server.listen - В чем разница?
Включение HTTPS в express.js
Корректный способ вернуть JSON с использованием Node.js или Express