579 Stimmen

ExpressJS Wie strukturiert man eine Anwendung?

Ich verwende das ExpressJS-Webframework für NodeJS.

Leute, die ExpressJS verwenden, legen ihre Umgebungen (Entwicklung, Produktion, Test...), ihre Routen usw. auf dem app.js . Ich denke, dass es nicht ein schöner Weg, weil, wenn Sie eine große Anwendung haben, app.js ist zu groß!

Ich möchte gerne diese Verzeichnisstruktur haben:

| my-application
| -- app.js
| -- config/
     | -- environment.js
     | -- routes.js

Hier ist mein Code:

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

Mein Code funktioniert gut und ich denke, dass die Struktur der Verzeichnisse schön ist. Allerdings musste der Code angepasst werden und ich bin mir nicht sicher, ob er gut/schön ist.

Ist es besser, meine Struktur von Verzeichnissen zu verwenden und den Code anzupassen oder einfach eine Datei (app.js) zu verwenden?

Vielen Dank für Ihre Ratschläge!

352voto

Peter Lyons Punkte 137811

OK, es ist eine Weile her, und dies ist eine beliebte Frage, so habe ich vorausgegangen und erstellt ein Gerüst github Repository mit JavaScript-Code und eine lange README, wie ich eine mittelgroße express.js-Anwendung zu strukturieren mag.

focusaurus/express_code_structure ist das Repo mit dem neuesten Code dafür. Pull-Anfragen sind willkommen.

Hier ist ein Schnappschuss der README, da Stackoverflow keine Just-a-Link-Antworten mag. Ich werde einige Aktualisierungen vornehmen, da dies ein neues Projekt ist, das ich weiterhin aktualisieren werde, aber letztendlich wird das Github-Repository der aktuelle Ort für diese Informationen sein.


Express-Code-Struktur

Dieses Projekt ist ein Beispiel dafür, wie man eine mittelgroße express.js-Webanwendung organisiert.

Aktuell bis mindestens express v4.14 Dezember 2016

Build Status

js-standard-style

Wie groß ist Ihre Anwendung?

Webanwendungen sind nicht alle gleich, und es gibt meiner Meinung nach keine einheitliche Codestruktur, die auf alle express.js-Anwendungen angewendet werden sollte.

Wenn Ihre Anwendung klein ist, brauchen Sie keine so tiefe Verzeichnisstruktur, wie sie hier gezeigt wird. Halten Sie es einfach und legen Sie eine Handvoll von .js Dateien im Stammverzeichnis Ihres Repositorys und Sie sind fertig. Voilà.

Wenn Ihre Anwendung sehr groß ist, müssen Sie sie irgendwann in verschiedene npm-Pakete aufteilen. Im Allgemeinen scheint der node.js-Ansatz viele kleine Pakete zu bevorzugen, zumindest für Bibliotheken, und Sie sollten Ihre Anwendung aufbauen, indem Sie mehrere npm-Pakete verwenden, sobald dies Sinn macht und den Overhead rechtfertigt. Wenn Ihre Anwendung wächst und ein Teil des Codes eindeutig außerhalb Ihrer Anwendung wiederverwendbar wird oder ein eindeutiges Subsystem darstellt, verschieben Sie ihn in ein eigenes Git-Repository und machen Sie daraus ein eigenständiges npm-Paket.

Also Der Schwerpunkt dieses Projekts liegt auf der Darstellung einer praktikablen Struktur für eine mittelgroße Anwendung.

Wie sieht Ihre Gesamtarchitektur aus?

Es gibt viele Ansätze für die Erstellung einer Webanwendung, z. B.

  • Serverseitiges MVC a la Ruby on Rails
  • Einseitige Anwendungen im Stil von MongoDB/Express/Angular/Node (MEAN)
  • Einfache Website mit einigen Formularen
  • Modelle/Operationen/Anzeigen/Ereignisse a la MVC ist tot, es ist an der Zeit, weiterzumachen
  • und viele andere sowohl aktuelle als auch historische

Jedes dieser Verzeichnisse passt gut in eine andere Verzeichnisstruktur. Für die Zwecke dieses Beispiels handelt es sich nur um ein Gerüst und nicht um eine voll funktionsfähige Anwendung, aber ich gehe von den folgenden zentralen Architekturpunkten aus:

  • Die Website hat einige traditionelle statische Seiten/Templates
  • Der "Anwendungsteil" der Website wurde im Stil einer Single Page Application entwickelt
  • Die Anwendung stellt dem Browser eine API im REST/JSON-Stil zur Verfügung
  • Die Anwendung modelliert eine einfache Geschäftsdomäne, in diesem Fall eine Autohausanwendung

Und was ist mit Ruby on Rails?

Es wird ein Thema in diesem Projekt sein, dass viele der Ideen, die in Ruby on Rails verkörpert werden, und die "Convention over Configuration"-Entscheidungen, die sie angenommen haben, obwohl sie weithin akzeptiert und verwendet werden, eigentlich nicht sehr hilfreich sind und manchmal das Gegenteil von dem sind, was dieses Repository empfiehlt.

Mein Hauptpunkt ist, dass es grundlegende Prinzipien für die Organisation von Code gibt, und basierend auf diesen Prinzipien machen die Ruby on Rails-Konventionen (meistens) für die Ruby on Rails-Community Sinn. Diese Konventionen einfach gedankenlos zu übernehmen, geht jedoch am Thema vorbei. Sobald Sie die Grundprinzipien verstanden haben, werden ALLE Ihre Projekte gut organisiert und übersichtlich sein: Shell-Skripte, Spiele, mobile Anwendungen, Unternehmensprojekte, sogar Ihr Home-Verzeichnis.

Für die Rails-Community ist es wichtig, dass ein einzelner Rails-Entwickler von einer Anwendung zur nächsten wechseln kann und jedes Mal mit der Anwendung vertraut ist. Dies ist sehr sinnvoll, wenn Sie 37 Signale oder Pivotal Labs sind, und hat Vorteile. In der Welt des serverseitigen JavaScript ist der allgemeine Ethos einfach viel wilder, alles ist möglich, und wir haben kein Problem damit. So sind wir nun mal. Wir sind daran gewöhnt. Selbst innerhalb von express.js ist es ein enger Verwandter von Sinatra, nicht von Rails, und Konventionen von Rails zu übernehmen, ist normalerweise nicht hilfreich. Ich würde sogar sagen Prinzipien vor Konvention vor Konfiguration .

Grundlegende Prinzipien und Motivationen

  • Geistig handhabbar sein

    • Das Gehirn kann nur eine kleine Anzahl von zusammenhängenden Dingen auf einmal verarbeiten und darüber nachdenken. Deshalb benutzen wir Verzeichnisse. Sie helfen uns, mit Komplexität umzugehen, indem wir uns auf kleine Teile konzentrieren.
  • Angemessene Größe

    • Erstellen Sie keine "Herrenhaus-Verzeichnisse", in denen es nur eine Datei gibt, die 3 Verzeichnisse weiter unten liegt. Sie können dies in der Ansible Bewährte Praktiken die kleine Projekte dazu zwingt, mehr als 10 Verzeichnisse für mehr als 10 Dateien anzulegen, obwohl ein Verzeichnis mit 3 Dateien viel besser geeignet wäre. Sie fahren nicht mit dem Bus zur Arbeit (es sei denn, Sie sind ein Busfahrer, aber selbst dann fahren Sie mit dem Bus zur Arbeit und nicht zur Arbeit), also erstellen Sie keine Dateisystemstrukturen, die nicht durch die tatsächlichen Dateien darin gerechtfertigt sind.
  • Modular, aber pragmatisch sein

    • Die Node-Community bevorzugt insgesamt kleine Module. Alles, was sich sauber aus Ihrer Anwendung herauslösen lässt, sollte in ein Modul extrahiert werden, entweder für den internen Gebrauch oder zur Veröffentlichung auf npm. Für die mittelgroßen Anwendungen, um die es hier geht, kann der Overhead jedoch den Arbeitsablauf ermüden, ohne dass dies einen entsprechenden Nutzen bringt. Wenn Sie also etwas Code haben, der herausgefiltert werden soll, aber nicht genug, um ein komplett separates npm-Modul zu rechtfertigen, betrachten Sie es einfach als ein " Proto-Baustein "mit der Erwartung, dass sie bei Überschreiten einer bestimmten Größenschwelle herausgezogen wird.
    • Einige Leute wie @hij1nx sogar eine app/node_modules Verzeichnis und haben package.json Dateien im Proto-Baustein Verzeichnisse, um diesen Übergang zu erleichtern und als Erinnerung zu dienen.
  • Code leicht auffindbar sein

    • Unser Ziel ist es, dass ein Entwickler bei einer zu erstellenden Funktion oder einem zu behebenden Fehler keine Schwierigkeiten hat, die betreffenden Quelldateien zu finden.
    • Die Namen sind aussagekräftig und genau
    • lästiger Code vollständig entfernt wird und nicht in einer verwaisten Datei verbleibt oder nur auskommentiert wird
  • Suchfreundlich sein

    • Der gesamte Quellcode der Erstanbieter befindet sich in der app Verzeichnis, damit Sie cd dort find/grep/xargs/ag/ack/etc ausführen und sich nicht von den Übereinstimmungen Dritter ablenken lassen
  • Verwenden Sie einfache und eindeutige Bezeichnungen

    • npm scheint jetzt alle Paketnamen in Kleinbuchstaben zu verlangen. Ich finde das meist schrecklich, aber ich muss der Herde folgen, also sollten Dateinamen mit kebab-case obwohl der Variablenname dafür in JavaScript lauten muss camelCase denn - ist ein Minuszeichen in JavaScript.
    • der Name der Variablen entspricht dem Basisnamen des Modulpfads, aber mit kebab-case umgewandelt in camelCase
  • Gruppierung nach Kopplung, nicht nach Funktion

    • Dies ist eine große Abweichung von der Ruby on Rails-Konvention von app/views , app/controllers , app/models usw.
    • Funktionen werden zu einem vollständigen Stapel hinzugefügt, daher möchte ich mich auf einen vollständigen Stapel von Dateien konzentrieren, die für meine Funktion relevant sind. Wenn ich dem Benutzermodell ein Telefonnummernfeld hinzufüge, interessiert mich kein anderer Controller als der Benutzer-Controller, und ich interessiere mich für kein anderes Modell als das Benutzermodell.
    • Anstatt also 6 Dateien zu bearbeiten, die sich jeweils in einem eigenen Verzeichnis befinden und tonnenweise andere Dateien in diesen Verzeichnissen zu ignorieren, ist dieses Repository so organisiert, dass alle Dateien, die ich für die Erstellung eines Features benötige, an einem Ort zusammengefasst sind
    • Es liegt in der Natur von MVC, dass die Benutzeransicht mit dem Benutzer-Controller gekoppelt ist, der wiederum mit dem Benutzermodell gekoppelt ist. Wenn ich also das Benutzermodell ändere, ändern sich diese 3 Dateien oft gemeinsam, aber der Deals-Controller oder der Customer-Controller sind entkoppelt und daher nicht beteiligt. Dasselbe gilt normalerweise auch für Nicht-MVC-Designs.
    • MVC oder MOVE-Stil Entkopplung in Bezug auf die Code geht in welchem Modul wird immer noch gefördert, aber die Verbreitung der MVC-Dateien in Geschwister Verzeichnisse ist nur ärgerlich.
    • So hat jede meiner Routendateien den Teil der Routen, der ihr gehört. Ein Schienen-Stil routes.rb Datei ist praktisch, wenn man einen Überblick über alle Routen in der App haben möchte, aber wenn man tatsächlich Funktionen entwickelt und Fehler behebt, interessiert man sich nur für die Routen, die für das Stück, das man ändert, relevant sind.
  • Tests neben dem Code speichern

    • Dies ist nur ein Beispiel für "Gruppierung durch Kopplung", aber ich wollte es besonders hervorheben. Ich habe viele Projekte geschrieben, bei denen die Tests in einem parallelen Dateisystem mit dem Namen "tests" liegen, und jetzt, wo ich angefangen habe, meine Tests in dasselbe Verzeichnis wie den zugehörigen Code zu legen, werde ich nie wieder zurückgehen. Das ist modularer und in Texteditoren viel einfacher zu handhaben und erleichtert den "../../ "-Pfadunsinn erheblich. Wenn Sie Zweifel haben, probieren Sie es an ein paar Projekten aus und entscheiden Sie selbst. Ich werde nichts weiter tun, um Sie davon zu überzeugen, dass es besser ist.
  • Reduzierung der Querschnittskopplung mit Events

    • Es ist einfach zu denken: "OK, immer wenn ein neues Geschäft erstellt wird, möchte ich eine E-Mail an alle Vertriebsmitarbeiter senden", und dann einfach den Code zum Senden dieser E-Mails in die Route zum Erstellen von Geschäften einfügen.
    • Diese Kopplung verwandelt Ihre App jedoch letztendlich in einen riesigen Schlammball.
    • Stattdessen sollte das DealModel nur ein "create"-Ereignis auslösen und sich nicht bewusst sein, was das System sonst noch als Reaktion darauf tun könnte.
    • Wenn Sie auf diese Weise programmieren, ist es viel einfacher, den gesamten benutzerbezogenen Code in app/users weil es kein Rattennest von gekoppelter Geschäftslogik gibt, das die Reinheit der Benutzercodebasis verunreinigt.
  • Der Codefluss ist nachvollziehbar

    • Machen Sie keine magischen Dinge. Laden Sie keine Dateien aus magischen Verzeichnissen im Dateisystem automatisch. Sei nicht Rails. Die Anwendung beginnt bei app/server.js:1 und Sie können alles sehen, was geladen und ausgeführt wird, indem Sie dem Code folgen.
    • Machen Sie keine DSLs für Ihre Routen. Führen Sie keine alberne Metaprogrammierung durch, wenn sie nicht erforderlich ist.
    • Wenn Ihre Anwendung so groß ist, dass sie magicRESTRouter.route(somecontroller, {except: 'POST'}) ist ein großer Gewinn für Sie über 3 grundlegende app.get , app.put , app.del Wenn Sie mit einer monolithischen Anwendung arbeiten, die zu groß ist, um sie effektiv zu bearbeiten, werden Sie wahrscheinlich eine solche Anwendung bauen. Machen Sie sich schick für große Erfolge, nicht für die Umwandlung von 3 einfachen Zeilen in 1 komplexe Zeile.
  • Dateinamen in Kleinbuchstaben verwenden

    • Dieses Format vermeidet Probleme mit der Groß- und Kleinschreibung im Dateisystem auf verschiedenen Plattformen.
    • npm verbietet Großbuchstaben in neuen Paketnamen, und das funktioniert gut mit diesem

      express.js-Besonderheiten

  • Verwenden Sie nicht app.configure . Es ist fast völlig nutzlos, und man braucht es einfach nicht. Er ist in vielen Standardtexten enthalten, weil er sinnlos kopiert wurde.

  • DIE REIHENFOLGE VON MIDDLEWARE UND ROUTEN IN EXPRESS IST WICHTIG!!!

    • Fast jedes Routing-Problem, das ich auf Stackoverflow sehe, ist ein Problem mit der Express-Middleware
    • Im Allgemeinen möchten Sie, dass Ihre Routen entkoppelt sind und sich nicht so sehr auf die Reihenfolge verlassen
    • Verwenden Sie nicht app.use für Ihre gesamte Anwendung, wenn Sie diese Middleware wirklich nur für 2 Routen benötigen (ich schaue Sie an, body-parser )
    • Vergewissern Sie sich, dass Sie am Ende GENAU diese Reihenfolge haben:
      1. Jede superwichtige anwendungsweite Middleware
      2. Alle Ihre Routen und verschiedene Routen-Middlewares
      3. THEN Fehlerbehandler
  • Da express.js von Sinatra inspiriert ist, geht es leider davon aus, dass alle Routen in server.js und es wird klar sein, wie sie angeordnet sind. Für eine mittelgroße Anwendung ist es schön, die Dinge in separate Routenmodule aufzuteilen, aber es birgt die Gefahr einer ungeordneten Middleware

Der App-Symlink-Trick

Es gibt viele Ansätze, die von der Gemeinschaft im großen Gist beschrieben und ausführlich diskutiert werden Bessere lokale require()-Pfade für Node.js . Vielleicht entscheide ich mich bald dafür, entweder "einfach mit vielen ../../../ " umzugehen oder die requireFrom modlue. Im Moment verwende ich jedoch den unten beschriebenen Trick mit den Symlinks.

Eine Möglichkeit zur Vermeidung von projektinternen Anforderungen mit lästigen relativen Pfaden wie require("../../../config") ist die Anwendung des folgenden Tricks:

  • Erstellen Sie einen Symlink unter node_modules für Ihre Anwendung
    • cd node_modules && ln -nsf ../app
  • hinzufügen. nur der Symlink node_modules/app selbst , nicht den gesamten Ordner node_modules, an git
    • git add -f node_modules/app
    • Ja, Sie sollten immer noch "node_modules" in Ihrem .gitignore Datei
    • Nein, Sie sollten "node_modules" nicht in Ihr Git-Repository aufnehmen. Einige Leute empfehlen Ihnen dies zu tun. Sie sind falsch.
  • Jetzt können Sie projektinterne Module mit diesem Präfix anfordern
    • var config = require("app/config");
    • var DealModel = require("app/deals/deal-model") ;
  • Im Grunde genommen funktionieren die projektinternen Requests damit ähnlich wie die Requests für externe npm-Module.
  • Tut mir leid, Windows-Benutzer, Sie müssen sich an die relativen Pfade des übergeordneten Verzeichnisses halten.

Konfiguration

Generell sollten Module und Klassen so kodiert werden, dass sie nur ein einfaches JavaScript erwarten options Objekt übergeben. Nur app/server.js sollte die app/config.js Modul. Von dort aus kann es kleine options Objekte, um Subsysteme nach Bedarf zu konfigurieren, aber jedes Subsystem an ein großes globales Konfigurationsmodul voller zusätzlicher Informationen zu koppeln, ist eine schlechte Kopplung.

Versuchen Sie, die Erstellung von DB-Verbindungen zu zentralisieren und diese an Subsysteme weiterzugeben, anstatt Verbindungsparameter zu übergeben und die Subsysteme selbst ausgehende Verbindungen herstellen zu lassen.

NODE_ENV

Dies ist eine weitere verlockende, aber schreckliche Idee, die von Rails übernommen wurde. Es sollte genau 1 Platz in Ihrer App sein, app/config.js die sich mit dem NODE_ENV Umgebungsvariable. Alles andere sollte eine explizite Option als Klassenkonstruktorargument oder Modulkonfigurationsparameter annehmen.

Wenn das E-Mail-Modul eine Option hat, wie E-Mails zugestellt werden sollen (SMTP, nach stdout protokollieren, in eine Warteschlange stellen usw.), sollte es eine Option wie {deliver: 'stdout'} aber es sollte auf keinen Fall prüfen NODE_ENV .

Tests

Ich bewahre meine Testdateien jetzt im selben Verzeichnis auf wie den zugehörigen Code und verwende Namenskonventionen für die Dateierweiterung, um die Tests vom Produktionscode zu unterscheiden.

  • foo.js hat den Code des Moduls "foo".
  • foo.tape.js hat die knotenbasierten Tests für foo und befindet sich im selben Verzeichnis
  • foo.btape.js kann für Tests verwendet werden, die in einer Browserumgebung ausgeführt werden müssen

Ich verwende Dateisystem-Globs und die find . -name '*.tape.js' um bei Bedarf Zugriff auf alle meine Tests zu erhalten.

Wie man den Code innerhalb der einzelnen .js Moduldatei

Bei diesem Projekt geht es hauptsächlich darum, wo Dateien und Verzeichnisse abgelegt werden, und ich möchte nicht viel mehr dazu sagen, aber ich möchte nur erwähnen, dass ich meinen Code in drei verschiedene Abschnitte einteile.

  1. Der Eröffnungsblock von CommonJS erfordert Aufrufe zur Angabe von Abhängigkeiten
  2. Hauptcodeblock aus reinem JavaScript. Hier gibt es keine CommonJS-Verschmutzung. Verweisen Sie nicht auf exports, module oder require.
  3. Schließen des CommonJS-Blocks zum Einrichten von Exporten

53voto

dthree Punkte 18379

Im Folgenden wird die Antwort von Peter Lyons wörtlich wiedergegeben, die von Coffeescript auf Vanilla JS portiert wurde, wie von mehreren anderen gefordert. Peters Antwort ist sehr gut, und jeder, der über meine Antwort abstimmt, sollte auch über seine abstimmen.


Konfigurieren Sie

Was Sie tun, ist in Ordnung. Ich möchte meinen eigenen Konfigurations-Namensraum in einer Top-Ebene einrichten config.js Datei mit einem verschachtelten Namespace wie diesem.

// Set the current environment to true in the env object
var currentEnv = process.env.NODE_ENV || 'development';
exports.appName = "MyApp";
exports.env = {
  production: false,
  staging: false,
  test: false,
  development: false
};  
exports.env[currentEnv] = true;
exports.log = {
  path: __dirname + "/var/log/app_#{currentEnv}.log"
};  
exports.server = {
  port: 9600,
  // In staging and production, listen loopback. nginx listens on the network.
  ip: '127.0.0.1'
};  
if (currentEnv != 'production' && currentEnv != 'staging') {
  exports.enableTests = true;
  // Listen on all IPs in dev/test (for testing from other machines)
  exports.server.ip = '0.0.0.0';
};
exports.db {
  URL: "mongodb://localhost:27017/#{exports.appName.toLowerCase()}_#{currentEnv}"
};

Dies ist für die Bearbeitung durch Systemadministratoren geeignet. Wenn ich dann etwas brauche, wie die DB-Verbindungsinformationen, ist es

require('./config').db.URL

Routen/Controller

Ich lasse meine Routen gerne bei meinen Kontrolleuren und organisiere sie in einem app/controllers Unterverzeichnis. Dann kann ich sie hochladen und sie die benötigten Routen hinzufügen lassen.

In meinem app/server.js javascript-Datei, die ich verwende:

[
  'api',
  'authorization',
  'authentication',
  'domains',
  'users',
  'stylesheets',
  'javascripts',
  'tests',
  'sales'
].map(function(controllerName){
  var controller = require('./controllers/' + controllerName);
  controller.setup(app);
});

Ich habe also Dateien wie:

app/controllers/api.js
app/controllers/authorization.js
app/controllers/authentication.js
app/controllers/domains.js

Und in meinem Domänencontroller habe ich zum Beispiel eine setup Funktion wie folgt.

exports.setup = function(app) {
  var controller = new exports.DomainController();
  var route = '/domains';
  app.post(route, controller.create);
  app.put(route, api.needId);
  app.delete(route, api.needId);
  route = '/domains/:id';
  app.put(route, controller.loadDomain, controller.update);
  app.del(route, controller.loadDomain, function(req, res){
    res.sendJSON(req.domain, status.OK);
  });
}

Ansichten

Ansichten einfügen app/views wird der übliche Ort. Ich lege es so aus.

app/views/layout.jade
app/views/about.jade
app/views/user/EditUser.jade
app/views/domain/EditDomain.jade

Statische Dateien

Gehen Sie in einem public Unterverzeichnis.

Github/Semver/NPM

Legen Sie eine README.md Markdown-Datei in Ihrem Git Repo Root für Github an.

Legen Sie eine package.json-Datei mit einer semantische Version Nummer in Ihrem Git-Repositorium Root für NPM.

50voto

Sandro Munda Punkte 38320

Meine Frage wurde im April 2011 gestellt, sie ist also ziemlich alt. Während dieser Zeit konnte ich meine Erfahrungen mit Express.js und der Architektur einer mit dieser Bibliothek geschriebenen Anwendung verbessern. Daher teile ich hier meine Erfahrungen.

Hier ist meine Verzeichnisstruktur:

 app.js   // main entry
 config   // The configuration of my applications (logger, global config, ...)
 models   // The model data (e.g. Mongoose model)
 public   // The public directory (client-side code)
 routes   // The route definitions and implementations
 services // The standalone services (Database service, Email service, ...)
 views    // The view rendered by the server to the client (e.g. Jade, EJS, ...)

App.js

Das Ziel der app.js Datei dient dem Bootstrap der expressjs-Anwendung. Sie lädt das Konfigurationsmodul, das Loggermodul, wartet auf die Datenbankverbindung, ..., und startet den Express-Server.

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

  // Configure the application.
  app.configure(function () {
    // ... ... ...
  });
  app.configure('production', function () {
    // ... ... ...
  });
  app.configure('development', function () {
    // ... ... ...
  });

  var server = http.createServer(app);

  // Load all routes.
  require('./routes')(app);

  // Listen on http port.
  server.listen(3000);
}

database.connect(function (err) {
  if (err) { 
    // ...
  }
  main();
});

Routen/

Das Verzeichnis routes hat eine index.js Datei. Ihr Ziel ist es, eine Art Magie einzuführen, um alle anderen Dateien innerhalb der routes/ Verzeichnis. Hier ist die Umsetzung:

/**
 * This module loads dynamically all routes modules located in the routes/
 * directory.
 */
'use strict';
var fs = require('fs');
var path = require('path');

module.exports = function (app) {
  fs.readdirSync('./routes').forEach(function (file) {
    // Avoid to read this current file.
    if (file === path.basename(__filename)) { return; }

    // Load the route file.
    require('./' + file)(app);
  });
};

Mit diesem Modul ist es wirklich einfach, eine neue Routendefinition und -implementierung zu erstellen. Für Beispiele, hello.js :

function hello(req, res) {
  res.send('Hello world');
}

module.exports = function (app) {
  app.get('/api/hello_world', hello);
};

Jedes Streckenmodul ist Eigenständig .

17voto

neebz Punkte 11259

Ich denke, das ist eine großartige Möglichkeit, das zu tun. Nicht auf express beschränkt, aber ich habe gesehen, eine ganze Reihe von node.js-Projekte auf github tun die gleiche Sache. Sie nehmen Sie die Konfigurationsparameter + kleinere Module (in einigen Fällen jeder URI) sind in separaten Dateien berücksichtigt.

Ich würde empfehlen, die express-spezifischen Projekte auf github durchzugehen, um eine Idee zu bekommen. IMO die Art und Weise, die Sie tun, ist richtig.

17voto

Simon Fakir Punkte 1581

Es ist jetzt Ende 2015 und nach der Entwicklung meiner Struktur seit 3 Jahren und in kleinen und großen Projekten. Fazit?

Machen Sie nicht eine große MVC, sondern trennen Sie sie in Module

Also...

Und warum?

  • Normalerweise arbeitet man an einem Modul (z.B. Produkte), das man unabhängig davon ändern kann.

  • Sie können Module wiederverwenden

  • Sie können es auch separat testen

  • Sie können es separat ersetzen

  • Sie haben klare (stabile) Schnittstellen

    -Spätestens, wenn mehrere Entwickler arbeiten, hilft die Modultrennung

Le site nodebootstrap Projekt hat einen ähnlichen Ansatz wie meine endgültige Struktur. ( github )

Wie sieht diese Struktur aus?

  1. Kleine, gekapselte Module jeweils mit separatem MVC

  2. Jedes Modul hat eine package.json

  3. Prüfung als Teil der Struktur (in jedem Modul)

  4. Globale Konfiguration , Bibliotheken und Dienstleistungen

  5. Integriertes Docker, Cluster, für immer

Ordnerübersicht (siehe Ordner lib für Module):

nodebootstrap structure

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X