Как структурировать приложение express.js? - PullRequest
102 голосов
/ 12 октября 2011

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

Ответы [ 4 ]

82 голосов
/ 12 октября 2011

У меня есть мое разбиение следующим образом:

~/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 уровень вверх, а затем вниз к моделям)


EDIT 4

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

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

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


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

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


EDIT 2

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

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


EDIT 1

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

9 голосов
/ 12 октября 2011

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

Если говорить более конкретно о разделении app.js У меня естьследующий app.js file

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

Просто для примера давайте рассмотрим маршрутизацию файл

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

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

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

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

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

1 голос
/ 26 сентября 2013

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

0 голосов
/ 19 июня 2019

Мои приложения построены поверх инструмента экспресс-генератора.Вы можете установить его, запустив npm install express-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;

Надеюсь, это помогло ответить на ваш вопрос!Желаем удачи!

...