Как структурировать приложение express.js?

Существует ли общее соглашение для разбивки и модуляции файла app.js в приложении Express.js? Или это общепринято для хранения всего в одном файле?

Ответ 1

Я раскололся следующим образом:

~/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

Я использую Exports, чтобы вернуть то, что релевантно. Например, в моделях, которые я делаю:

module.exports = mongoose.model('PhoneNumber', PhoneNumberSchema);

а затем, если мне нужно создать номер телефона, это просто:

var PhoneNumber = require('../models/phoneNumber');
var phoneNumber = new PhoneNumber();

если мне нужно использовать схему, тогда PhoneNumber.schema

(который предполагает, что мы работаем из папки маршрутов и должны идти 1 уровень вверх, а затем вниз к моделям)


EDIT 4

express wiki имеет список фреймворков, построенных поверх него.

Из них я думаю, что Twitter matador структурирован довольно хорошо. Мы фактически использовали очень похожий подход к тому, как они загружают части приложения.

derby.js также выглядит чрезвычайно интересно. Это сродни meteor без всякой шумихи и на самом деле дает кредит, где кредит должен (в частности, node и выразить).


РЕДАКТИРОВАТЬ 3

Если вы являетесь поклонником CoffeeScript (я не являюсь) и reeeeaaaaally хотят L & F of Rails, есть также Tower.js.


EDIT 2

Если вы знакомы с Rails и не против перетекания некоторых концепций, Locomotive. Это легкая рама, построенная на Express. Он имеет очень похожую структуру как RoR и переносит некоторые из более элементарных понятий (таких как маршрутизация).

Стоит проверить, даже если вы не планируете его использовать.


РЕДАКТИРОВАТЬ 1

nodejs-express-mongoose-demo очень похож на то, как я структурирован. Проверьте это.

Ответ 2

Предупреждение: ссылочный код, который я взломал для нокаута node, он вроде работает, но далек от элегантности или полировки.

Более конкретно о разделении app.js У меня есть следующий файл app.js

var express = require('express'),
    bootstrap = require('./init/bootstrap.js'),
    app = module.exports = express.createServer();

bootstrap(app);

В основном это означает, что я размещаю все мои загрузочные файлы в отдельном файле, а затем загружаю сервер.

Итак, что делает bootstrap do?

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 во время выполнения.
  • У меня есть код, который устанавливает все мои маршруты.
  • Я называю этот небольшой модуль nko
  • Наконец, я запускаю сервер, слушая порт.

Просто рассмотрим, например, файл routing

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);
        }
    });

Здесь я punch socket.io фактически использую авторизацию, а затем позволяю любому tom и jack разговаривать с моим сервером socket.io

    routes.forEach(function(file) {
        var route = require(routeUrl + file),
            model = require(modelUrl + file);

        route(app, model, io);
    });
};

Здесь я запускаю свои маршруты, передавая соответствующую модель в каждый объект маршрута, возвращенный из файла маршрута.

По сути, это то, что вы организуете все в маленькие небольшие модули, а затем создаете механизм начальной загрузки.

Мой другой проект (мой блог) имеет файл инициализации с аналогичной структурой.

Отказ от ответственности: блог сломан и не работает, я над ним работаю.

Ответ 3

Для поддерживающей организации маршрутизации вы можете проверить эту статью о express-routescan node и попробуйте. Это лучшее решение для меня.