Как структурировать приложение express.js?
Существует ли общее соглашение для разделения и модульности app.js
файл в приложении Express.js? Или все это обычно хранится в одном файле?
3 ответа
Я разбил мой следующим образом:
~/app
|~controllers
| |-monkey.js
| |-zoo.js
|~models
| |-monkey.js
| |-zoo.js
|~views
| |~zoos
| |-new.jade
| |-_form.jade
|~test
| |~controllers
| |-zoo.js
| |~models
| |-zoo.js
|-index.js
Я использую Экспорт, чтобы вернуть то, что имеет значение. Например, в моделях я делаю:
module.exports = mongoose.model('PhoneNumber', PhoneNumberSchema);
и затем, если мне нужно создать номер телефона, это так просто, как:
var PhoneNumber = require('../models/phoneNumber');
var phoneNumber = new PhoneNumber();
если мне нужно использовать схему, то PhoneNumber.schema
(что предполагает, что мы работаем из папки маршрутов и должны перейти на 1 уровень вверх, а затем вниз к моделям)
РЕДАКТИРОВАТЬ 4
У экспресс-вики есть список фреймворков, построенных поверх него.
Из них, я думаю, что матадор Твиттера структурирован довольно хорошо. На самом деле мы использовали очень похожий подход к тому, как они загружают части приложения.
derby.js также выглядит крайне интересно. Это похоже на метеор без всякой ажиотажа и на самом деле дает кредит, где кредит должен (в частности, узел и экспресс).
РЕДАКТИРОВАТЬ 3
Если вы являетесь поклонником CoffeeScript (а я нет) и хотите получить L&F Rails, есть также Tower.js.
РЕДАКТИРОВАТЬ 2
Если вы знакомы с Rails и не возражаете против некоторых концепций, есть Locomotive. Это легкий каркас, построенный на Express. Он имеет очень похожую структуру с RoR и несет в себе некоторые элементарные понятия (например, маршрутизацию).
Это стоит проверить, даже если вы не планируете его использовать.
РЕДАКТИРОВАТЬ 1
https://github.com/madhums/nodejs-express-mongoose-demo очень похож на мою структуру. Проверьте это.
Предупреждение: ссылка на код, который я взломал вместе для нокаута узла, это работает, но далеко не изящно или отточено.
Чтобы быть более конкретным о разделении app.js
У меня есть следующий файл app.js
var express = require('express'),
bootstrap = require('./init/bootstrap.js'),
app = module.exports = express.createServer();
bootstrap(app);
По сути, это означает, что я помещаю всю свою загрузку в отдельный файл, а затем загружаю сервер.
Так что же делает бутстрап?
var configure = require("./app-configure.js"),
less = require("./watch-less.js"),
everyauth = require("./config-everyauth.js"),
routes = require("./start-routes.js"),
tools = require("buffertools"),
nko = require("nko"),
sessionStore = new (require("express").session.MemoryStore)()
module.exports = function(app) {
everyauth(app);
configure(app, sessionStore);
less();
routes(app, sessionStore);
nko('/9Ehs3Dwu0bSByCS');
app.listen(process.env.PORT);
console.log("server listening on port xxxx");
};
Ну, это разбивает все настройки инициализации сервера на хорошие куски. конкретно
- У меня есть блок, который настраивает все мои удаленные проверки подлинности OAuth с использованием EveryAuth.
- У меня есть кусок, который настраивает мое приложение (в основном вызов
app.configure
) - У меня есть немного кода, который меньше пробивает, поэтому он перекомпилирует любой из моих меньше в css во время выполнения.
- У меня есть код, который устанавливает все мои маршруты
- Я называю этот маленький нко модуль
- Наконец я запускаю сервер, прослушивая порт.
Просто для примера давайте посмотрим на файл маршрутизации
var fs = require("fs"),
parseCookie = require('connect').utils.parseCookie;
module.exports = function(app, sessionStore) {
var modelUrl = __dirname + "/../model/",
models = fs.readdirSync(modelUrl),
routeUrl = __dirname + "/../route/"
routes = fs.readdirSync(routeUrl);
Здесь я загружаю все свои модели и маршруты в виде массивов файлов.
Отказ от ответственности: readdirSync
только в порядке, когда вызывается, прежде чем запустить http-сервер (до .listen
). Вызов синхронных блокирующих вызовов во время запуска сервера просто делает код более читабельным (это в основном хак)
var io = require("socket.io").listen(app);
io.set("authorization", function(data, accept) {
if (data.headers.cookie) {
data.cookie = parseCookie(data.headers.cookie);
data.sessionId = data.cookie['express.sid'];
sessionStore.get(data.sessionId, function(err, session) {
if (err) {
return accept(err.message, false);
} else if (!(session && session.auth)) {
return accept("not authorized", false)
}
data.session = session;
accept(null, true);
});
} else {
return accept('No cookie', false);
}
});
Здесь я нажимаю socket.io, чтобы фактически использовать авторизацию, а не позволять любому тому и джеку общаться с моим сервером socket.io
routes.forEach(function(file) {
var route = require(routeUrl + file),
model = require(modelUrl + file);
route(app, model, io);
});
};
Здесь я начинаю свои маршруты, передавая соответствующую модель в каждый объект маршрута, возвращенный из файла маршрута.
По сути, Jist состоит в том, что вы организуете все в красивые маленькие модули и получаете механизм начальной загрузки.
Мой другой проект (мой блог) имеет файл инициализации с похожей структурой.
Отказ от ответственности: блог сломан и не строит, я работаю над этим.
Мои приложения создаются на основе инструмента экспресс-генератора. Вы можете установить его, запустив npm installexpress-generator -g
и запустите его, используя express <APP_NAME>
.
Чтобы дать вам представление, структура одного из моих небольших приложений выглядела так:
~/
|~bin
| |-www
|
|~config
| |-config.json
|
|~database
| |-database.js
|
|~middlewares
| |-authentication.js
| |-logger.js
|
|~models
| |-Bank.js
| |-User.js
|
|~routes
| |-index.js
| |-banks.js
| |-users.js
|
|~utilities
| |-fiat-converersion.js
|
|-app.js
|-package.json
|-package-lock.json
Одна крутая вещь, которая мне нравится в этой структуре, которую я в конечном итоге использую для любого разрабатываемого мной экспресс-приложения, - это способ организации маршрутов. Мне не нравилось запрашивать каждый файл маршрута в app.js иapp.use()
каждый маршрут, особенно когда файл становится больше. Таким образом, я нашел полезным сгруппировать и централизовать все моиapp.use()
в файле./routes/index.js.
В итоге мой app.js будет выглядеть примерно так:
...
const express = require('express');
const app = express();
...
require('./routes/index')(app);
и мой./routes/index.js будет выглядеть примерно так:
module.exports = (app) => {
app.use('/users', require('./users'));
app.use('/banks', require('./banks'));
};
Я умею просто require(./users)
потому что я написал пользовательский маршрут с помощью express.Router(), который позволяет мне "группировать" несколько маршрутов, а затем экспортировать их сразу, чтобы сделать приложение более модульным.
Это пример того, что вам подходит на моем маршруте./routers/users.js:
const router = require('express').Router();
router.post('/signup', async (req, res) => {
// Signup code here
});
module.exports = router;
Надеюсь, это помогло ответить на ваш вопрос! Удачи!
Для организации обслуживаемой маршрутизации вы можете проверить эту статью о модуле узла express-routcan и попробовать его. Это лучшее решение для меня.