web-dev-qa-db-fra.com

Vous voulez être clair sur la structure de l'application NodeJS (pile JavaScript complète)

Je voudrais connaître la structure d'une application NodeJS typique, car plus je lis et vois les projets, plus je suis confus, en particulier pour des questions comme celles-ci (ou même plus après avoir mis à jour cette question):

  1. Prenez la pile MEAN par exemple, d'après ce que je sais, NodeJS et Express s'occupent de la partie serveur, fournissant l'interface serveur, etc. MongoDB et Angular sont assez simples.

    Mais où devrait aller la logique métier? Dites si j'ai un controller.js qui contient une fonction, et le route.js le fichier lie la demande avec cette fonction de contrôleur. Ma question est: sous quel module ces fichiers appartiennent/s'exécutent sous (Express ou NodeJS?)

  2. Où est le point de départ d'une application NodeJS? Dire index.php est le point de départ d'une application PHP, mais où est-elle pour l'application NodeJS? Je peux voir que tous les projets Nodejs ont un fichier appelé server.js ou app.js, etc. (contenant quelque chose comme module.exports = app;) Mais comment NodeJS peut-il savoir quel fichier rechercher et exécuter?

Je suis un nouveau noob sur NodeJS, Express, sequelize.js/Mongoose, Jade/EJS mais je veux commencer un projet NodeJS. Pourriez-vous s'il vous plaît développer la fonction réelle que chaque module fournit et une introduction générale de la structure typique d'une application NodeJS empilée JS complète? Merci d'avance!

34
JustinHo

D'accord, c'est une question assez large et je ne suis certainement pas un expert, mais je ferai de mon mieux ici.

TL; DR

  • routes sont des contrôleurs qui indiquent quelle logique exécuter lorsqu'un utilisateur navigue sur son navigateur vers un certain chemin dans votre application, y compris les vues à rendre et les données à envoyer à ces vues
  • models ne sont que cela - des modèles de données dans votre application
  • module.exports = Indique à un fichier ce qu'il "exporte" exactement, c'est-à-dire ce code qui doit être exécuté ou accessible à partir de votre fichier d'application principal.
  • require(..) inclut un module. Vous pouvez définir cela sur une variable pour pouvoir appeler des fonctions de module plus tard, ou simplement exécuter une fonction si c'est tout ce que module.exports Renvoie.

La combinaison de ces techniques peut vous aider à définir un cadre solide pour chacune de vos applications.


Réponse longue

Express fournit un cadre solide pour structurer votre application Node.js. Node est complètement indépendant d'Express, mais en raison de la popularité d'Express, ils vont pratiquement de pair. Une fois installé, Express peut être utilisé pour générer un projet Web d'échafaudage (avec options) pour vous construire sur le dessus si vous le souhaitez.

Contrôleurs

Un projet généré créera /routes/index.js, Qui (si vous comprenez MVC) est essentiellement votre principal contrôleur. Un itinéraire en express s'écrit ainsi:

app.get('/path', function(req, res, next){ .. } );

Permet de décomposer cela: notre variable d'application (app) est informée que sur une demande GET à '/path' Pour exécuter une fonction de rappel anonyme avec des variables req, res, next (Demande, réponse, rappel respectivement). Je trouve utile de penser à cela comme un gestionnaire d'événements personnalisé.

Il est important de noter à ce stade que nous pourrions également appeler app.post Avec la même syntaxe pour les publications vers une URL que pour get.

Dans notre rappel anonyme, nous traitons toutes les données entrantes et rendons une vue pour l'utilisateur. C'est là que la plupart de ma logique métier se retrouve, il est donc logique de NE PAS utiliser de fonctions anonymes ici. Voici un exemple de rappel de base qui affiche simplement une page d'accueil:

app.get('/', function(req, res, next){

    //some business logic

    res.render('views/home');
});

Lorsque l'utilisateur essaie d'obtenir le chemin d'index de notre application (/), Nous rendons simplement notre vue home qui, depuis la racine de notre projet, est stockée dans un views dossier.

Mais que se passe-t-il si nous voulons modulariser cela afin de ne pas déclarer tous nos itinéraires dans notre app.js Ou server.js Principal?

Nous utilisons module.exports = .. Dans nos modules pour indiquer à notre serveur ce qu'il faut exactement inclure. Dans mon contrôleur, j'exporte une seule fonction qui prend l'application comme argument et l'utilise pour définir nos routes comme suit:

Contrôleurs/User.js

 module.exports = function(app){

    app.get('/users', function(req, res){
        var users = req.db.collection('users').find();
        if (!users) {
            console.log("no users found");
            res.redirect('/');
        } else {
            res.render('users/index', {users : users});
        }
    });

};

Ne vous inquiétez pas du code req.db, J'attache la base de données à la demande dans mon application mais cela n'est pas fait par défaut. Comprenez simplement que je reçois ici une liste des "utilisateurs" et que je redirige l'utilisateur vers l'index de mon application s'il n'y en a pas.

Modèles

Mongoose nous offre une excellente interface pour écrire des modèles. Avec mangouste, l'écriture de modèles est un processus en trois étapes:

  • Définir un schéma
  • Définir la logique du modèle
  • Générer et exporter le modèle

Voici un exemple de modèle User:

Modèles/User.js

var mongoose = require('mongoose'),
    userSchema = new mongoose.Schema({

        name: { type: String, required: true },
        joinDate: {type: Date, default: date.now }

    }),
    User = mongoose.model('user', userSchema);

module.exports = user;

Application serveur

module.exports Est utilisé pour nous aider à définir une certaine modularité de notre base de code. Lorsque nous exécutons une application de noeud, nous exécutons finalement un seul fichier JavaScript (vous avez déjà vu ce fichier avec server.js Ou app.js).

Pour éviter que ce fichier ne devienne trop volumineux avec plusieurs modèles et itinéraires, nous utilisons require(module) pour inclure du code provenant d'autres fichiers JS. module dans notre cas serait un chemin vers le module dont nous voulons avoir besoin. Si vous avez la structure de document suivante:

| Controllers
    - User.js
| Models
    - User.js
| Views
app.js

Pour inclure votre contrôleur utilisateur à partir de app.js, Vous devez écrire: require('./Controllers/User'). Puisque nos modules de contrôleur exportent simplement des fonctions, nous pouvons appeler cette fonction immédiatement après notre instruction require en ajoutant simplement des parenthèses à la fin (avec tous les paramètres requis). Inclure mes contrôleurs ressemble à ceci:

require('./Controllers/User')(app)

Je passe dans l'application réelle, car mon module (ci-dessous) exporte simplement une fonction qui ajoute une logique métier aux itinéraires de mon application. Cela doit seulement être appelé et jamais utilisé, donc je ne capture pas mon contrôleur en tant que variable pour appeler des méthodes plus tard.

L'inclusion de modèles est un peu différente, car nous souhaitons peut-être effectuer une opération définie par notre modèle. Nous pouvons le faire en modifiant un peu notre code requis:

var User = require('./Models/User');

Maintenant, nous pouvons appeler les méthodes de notre modèle utilisateur à tout moment. Mongoose nous offre gratuitement de nombreuses fonctionnalités de base:

User.find({}, function(err, users){ .. });

La fonction ci-dessus ira trouver tous nos utilisateurs, puis exécutera une fonction anonyme avec un potentiel err (est nul si aucun problème), puis une liste de nos utilisateurs au format JSON. Assez astucieux.

La combinaison de tous ces concepts permet de créer une application Web de base à l'aide d'Express et de Node.js. Veuillez me faire savoir dans les commentaires s'il y a quelque chose que je peux clarifier sur la façon dont j'utilise Express. Il s'agit d'une connaissance très superficielle, et je suggère de creuser dans la documentation et de regarder des plugins pour étendre les capacités de vos applications. Bonne chance!

41
Jordan Foreman