Esiste una convenzione comune per suddividere e modulare il app.js
file in un'applicazione Express.js ? O è comune conservare tutto in un unico file?
Esiste una convenzione comune per suddividere e modulare il app.js
file in un'applicazione Express.js ? O è comune conservare tutto in un unico file?
Risposte:
Ho il mio rotto come segue:
~/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
Uso le esportazioni per restituire ciò che è rilevante. Ad esempio, nei modelli che faccio:
module.exports = mongoose.model('PhoneNumber', PhoneNumberSchema);
e quindi se ho bisogno di creare un numero di telefono, è semplice come:
var PhoneNumber = require('../models/phoneNumber');
var phoneNumber = new PhoneNumber();
se ho bisogno di usare lo schema, allora PhoneNumber.schema
(il che presuppone che stiamo lavorando dalla cartella dei percorsi e che sia necessario salire di 1 livello e poi scendere ai modelli)
Il wiki express ha un elenco di framework costruiti sopra di esso.
Di questi, penso che il matador di Twitter sia strutturato abbastanza bene. In realtà abbiamo utilizzato un approccio molto simile al modo in cui caricano parti dell'app.
anche derby.js sembra estremamente interessante. È simile a meteor senza tutto il clamore e in realtà dà credito a dove è dovuto (in particolare, nodo ed espresso).
Se sei un fan di CoffeeScript (io non lo sono) e vuoi reeeeaaaaaally il L&F di Rails, c'è anche Tower.js .
Se hai familiarità con Rails e non ti dispiace il sanguinamento di alcuni concetti, c'è Locomotive . È un framework leggero costruito su Express. Ha una struttura molto simile a RoR e trasporta alcuni dei concetti più rudimentali (come il routing).
Vale la pena dare un'occhiata anche se non prevedi di usarlo.
nodejs-express-mongoose-demo è molto simile a come ho strutturato il mio. Controlla.
Attenzione: facendo riferimento al codice che ho hackerato insieme per il knockout del nodo, in qualche modo funziona ma è tutt'altro che elegante o raffinato.
Per essere più specifici sulla divisione, app.js
ho il seguente file app.js
var express = require('express'),
bootstrap = require('./init/bootstrap.js'),
app = module.exports = express.createServer();
bootstrap(app);
Questo significa fondamentalmente che metto tutto il mio bootstrap in un file separato, quindi avvio il server.
Allora cosa fa il bootstrap ?
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");
};
Bene, divide tutte le impostazioni di inizializzazione del server in bei pezzi. In particolare
app.configure
)Solo per esempio diamo un'occhiata al file di instradamento
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);
Qui carico tutti i miei modelli e percorsi come array di file.
Disclaimer: readdirSync
va bene solo se chiamato prima di avviare il server http (prima .listen
). Chiamare chiamate di blocco sincroniche all'avvio del server rende il codice più leggibile (è fondamentalmente un hack)
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);
}
});
Qui premo socket.io per utilizzare effettivamente l'autorizzazione piuttosto che lasciare che qualsiasi tom e jack parli con il mio server socket.io
routes.forEach(function(file) {
var route = require(routeUrl + file),
model = require(modelUrl + file);
route(app, model, io);
});
};
Qui inizio i miei percorsi passando il modello pertinente in ogni oggetto di percorso restituito dal file di percorso.
Fondamentalmente il succo è che organizzi tutto in piccoli moduli carini e poi hai un meccanismo di bootstrap.
L'altro mio progetto (il mio blog) ha un file init con una struttura simile .
Disclaimer: il blog è rotto e non si costruisce, ci sto lavorando.
Per l'organizzazione di routing mantenibile è possibile controllare questo articolo su l' espresso routescan modulo nodo e provarlo. Questa è la soluzione migliore per me.
Ho le mie app basate sullo strumento generatore di espresso. Puoi installarlo eseguendolo npm install express-generator -g
ed eseguirlo usando express <APP_NAME>
.
Per darti una prospettiva, una delle strutture della mia applicazione più piccola era simile a questa:
~/
|~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
Una cosa interessante che mi piace di questa struttura che finisco per adottare per qualsiasi applicazione express che sviluppo è il modo in cui sono organizzati i percorsi. Non mi piaceva dover richiedere ogni file di percorso in app.js e app.use()
ogni percorso, soprattutto quando il file diventa più grande. In quanto tale, ho trovato utile raggruppare e centralizzare tutto il mio app.use()
su un file ./routes/index.js.
Alla fine, il mio app.js avrà un aspetto simile a questo:
...
const express = require('express');
const app = express();
...
require('./routes/index')(app);
e il mio ./routes/index.js avrà un aspetto simile a questo:
module.exports = (app) => {
app.use('/users', require('./users'));
app.use('/banks', require('./banks'));
};
Sono in grado di farlo semplicemente require(./users)
perché ho scritto il percorso degli utenti utilizzando express.Router () che mi permette di "raggruppare" più percorsi e di esportarli contemporaneamente, con l'obiettivo di rendere l'applicazione più modulare.
Questo è un esempio di cosa andresti bene sul mio percorso ./routers/users.js:
const router = require('express').Router();
router.post('/signup', async (req, res) => {
// Signup code here
});
module.exports = router;
Spero che questo abbia aiutato a rispondere alla tua domanda! Buona fortuna!