W mojej express
aplikacji NodeJS mam app.js
kilka wspólnych tras. Następnie w wf.js
pliku chciałbym zdefiniować jeszcze kilka tras.
Jak mogę app.js
rozpoznać inne procedury obsługi tras zdefiniowane w wf.js
pliku?
Proste wymaganie nie działa.
W mojej express
aplikacji NodeJS mam app.js
kilka wspólnych tras. Następnie w wf.js
pliku chciałbym zdefiniować jeszcze kilka tras.
Jak mogę app.js
rozpoznać inne procedury obsługi tras zdefiniowane w wf.js
pliku?
Proste wymaganie nie działa.
Odpowiedzi:
Jeśli chcesz na przykład umieścić trasy w osobnym pliku , routes.js
możesz utworzyć routes.js
plik w ten sposób:
module.exports = function(app){
app.get('/login', function(req, res){
res.render('login', {
title: 'Express Login'
});
});
//other routes..
}
A potem możesz wymagać od obiektuapp.js
przekazania w ten sposób:app
require('./routes')(app);
Zobacz także te przykłady
https://github.com/visionmedia/express/tree/master/examples/route-separation
Chociaż to starsze pytanie, natknąłem się tutaj, szukając rozwiązania podobnego problemu. Po wypróbowaniu niektórych rozwiązań tutaj postanowiłem pójść w innym kierunku i pomyślałem, że dodam moje rozwiązanie każdemu, kto tu trafi.
W express 4.x można uzyskać instancję obiektu routera i zaimportować inny plik zawierający więcej tras. Możesz to zrobić rekurencyjnie, aby Twoje trasy importowały inne trasy, umożliwiając tworzenie łatwych w utrzymaniu ścieżek URL. Na przykład, jeśli mam już osobny plik trasy dla mojego punktu końcowego „/ testy” i chcę dodać nowy zestaw tras dla „/ testów / automatycznych”, mogę rozdzielić te trasy „/ automatyczne” na inny plik, aby mój plik „/ test” powinien być mały i łatwy w zarządzaniu. Pozwala również logicznie grupować trasy według ścieżki URL, co może być naprawdę wygodne.
Zawartość pliku ./app.js:
var express = require('express'),
app = express();
var testRoutes = require('./routes/tests');
// Import my test routes into the path '/test'
app.use('/tests', testRoutes);
Zawartość ./routes/tests.js
var express = require('express'),
router = express.Router();
var automatedRoutes = require('./testRoutes/automated');
router
// Add a binding to handle '/test'
.get('/', function(){
// render the /tests view
})
// Import my automated routes into the path '/tests/automated'
// This works because we're already within the '/tests' route so we're simply appending more routes to the '/tests' endpoint
.use('/automated', automatedRoutes);
module.exports = router;
Zawartość pliku ./routes/testRoutes/automated.js:
var express = require('express'),
router = express.Router();
router
// Add a binding for '/tests/automated/'
.get('/', function(){
// render the /tests/automated view
})
module.exports = router;
Opierając się na przykładzie @ShadowCloud, byłem w stanie dynamicznie uwzględnić wszystkie trasy w podkatalogu.
trasy / index.js
var fs = require('fs');
module.exports = function(app){
fs.readdirSync(__dirname).forEach(function(file) {
if (file == "index.js") return;
var name = file.substr(0, file.indexOf('.'));
require('./' + name)(app);
});
}
Następnie umieszczaj pliki tras w katalogu tras w następujący sposób:
trasy / test1.js
module.exports = function(app){
app.get('/test1/', function(req, res){
//...
});
//other routes..
}
Powtarzam to tyle razy, ile potrzebowałem, a potem w końcu umieszczam app.js
require('./routes')(app);
I opierając się jeszcze bardziej na poprzedniej odpowiedzi, ta wersja trasy / index.js zignoruje wszystkie pliki nie kończące się na .js (i sama)
var fs = require('fs');
module.exports = function(app) {
fs.readdirSync(__dirname).forEach(function(file) {
if (file === "index.js" || file.substr(file.lastIndexOf('.') + 1) !== 'js')
return;
var name = file.substr(0, file.indexOf('.'));
require('./' + name)(app);
});
}
.DS_Store
pliki i wszystko to psuje.
Umieść pełne rekurencyjne routing wszystkich .js
plików w /routes
folderze app.js
.
// Initialize ALL routes including subfolders
var fs = require('fs');
var path = require('path');
function recursiveRoutes(folderName) {
fs.readdirSync(folderName).forEach(function(file) {
var fullName = path.join(folderName, file);
var stat = fs.lstatSync(fullName);
if (stat.isDirectory()) {
recursiveRoutes(fullName);
} else if (file.toLowerCase().indexOf('.js')) {
require('./' + fullName)(app);
console.log("require('" + fullName + "')");
}
});
}
recursiveRoutes('routes'); // Initialize it
w /routes
umieścić whatevername.js
i zainicjować swoje trasy jak to:
module.exports = function(app) {
app.get('/', function(req, res) {
res.render('index', { title: 'index' });
});
app.get('/contactus', function(req, res) {
res.render('contactus', { title: 'contactus' });
});
}
Próbuję zaktualizować tę odpowiedź za pomocą „express”: „^ 4.16.3”. Ta odpowiedź jest podobna do ShortRound1911.
server.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const db = require('./src/config/db');
const routes = require('./src/routes');
const port = 3001;
const app = new express();
//...use body-parser
app.use(bodyParser.urlencoded({ extended: true }));
//...fire connection
mongoose.connect(db.url, (err, database) => {
if (err) return console.log(err);
//...fire the routes
app.use('/', routes);
app.listen(port, () => {
console.log('we are live on ' + port);
});
});
/src/routes/index.js
const express = require('express');
const app = express();
const siswaRoute = require('./siswa_route');
app.get('/', (req, res) => {
res.json({item: 'Welcome ini separated page...'});
})
.use('/siswa', siswaRoute);
module.exports = app;
/src/routes/siswa_route.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.json({item: 'Siswa page...'});
});
module.exports = app;
Mam nadzieję, że to może komuś pomóc. Miłego kodowania!
Jeśli używasz express-4.x z TypeScript i ES6, byłby to najlepszy szablon do użycia:
src/api/login.ts
import express, { Router, Request, Response } from "express";
const router: Router = express.Router();
// POST /user/signin
router.post('/signin', async (req: Request, res: Response) => {
try {
res.send('OK');
} catch (e) {
res.status(500).send(e.toString());
}
});
export default router;
src/app.ts
import express, { Request, Response } from "express";
import compression from "compression"; // compresses requests
import expressValidator from "express-validator";
import bodyParser from "body-parser";
import login from './api/login';
const app = express();
app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
app.get('/public/hc', (req: Request, res: Response) => {
res.send('OK');
});
app.use('/user', login);
app.listen(8080, () => {
console.log("Press CTRL-C to stop\n");
});
Znacznie czystszy niż przy użyciu var
i module.exports
.
Jedna poprawka do wszystkich tych odpowiedzi:
var routes = fs.readdirSync('routes')
.filter(function(v){
return (/.js$/).test(v);
});
Wystarczy użyć wyrażenia regularnego do filtrowania poprzez przetestowanie każdego pliku w tablicy. Nie jest rekurencyjny, ale odfiltruje foldery, które nie kończą się na .js
Wiem, że to stare pytanie, ale próbowałem wymyślić coś dla siebie i to jest miejsce, w którym skończyłem, więc chciałem rozwiązać moje podobne problemy na wypadek, gdyby ktoś miał takie same problemy, jak ja ”. mam. Istnieje ładny moduł węzła o nazwie consign, który wykonuje wiele rzeczy z systemu plików, które są tu widoczne dla ciebie (tj. - nie ma readdirSync). Na przykład:
Mam spokojną aplikację API, którą próbuję zbudować i chcę umieścić wszystkie żądania kierowane do „/ api / *” w celu uwierzytelnienia i chcę zapisać wszystkie moje trasy, które idą w interfejsie API, do ich własnego katalogu (nazwijmy to „api”). W głównej części aplikacji:
app.use('/api', [authenticationMiddlewareFunction], require('./routes/api'));
Wewnątrz katalogu tras mam katalog o nazwie „api” i plik o nazwie api.js. W api.js po prostu mam:
var express = require('express');
var router = express.Router();
var consign = require('consign');
// get all routes inside the api directory and attach them to the api router
// all of these routes should be behind authorization
consign({cwd: 'routes'})
.include('api')
.into(router);
module.exports = router;
Wszystko działało zgodnie z oczekiwaniami. Mam nadzieję, że to komuś pomoże.
Jeśli chcesz, aby osobny plik .js lepiej organizował trasy, po prostu utwórz zmienną w app.js
pliku wskazującą jego lokalizację w systemie plików:
var wf = require(./routes/wf);
następnie,
app.get('/wf', wf.foo );
gdzie .foo
w twoim wf.js
pliku zadeklarowana jest jakaś funkcja . na przykład
// wf.js file
exports.foo = function(req,res){
console.log(` request object is ${req}, response object is ${res} `);
}
wf.foo
itd., Ponieważ są one poza zakresem, tak jak w przypadku innych prezentowanych rozwiązań? Mam na myśli przypadek, w którym normalnie miałbyś dostęp do współużytkowanych zmiennych / funkcji w wf.foo, gdyby nie był oddzielony od app.js.
Napisałem małą wtyczkę do tego! miałem dość pisania tego samego kodu w kółko.
https://www.npmjs.com/package/js-file-req
Mam nadzieję, że to pomoże.
To prawdopodobnie najbardziej niesamowite pytanie / odpowiedź na pytanie o przepełnienie stosu. Ja kocham rozwiązań Sam / Brada powyżej. Pomyślałem, że włączy się z wersją asynchroniczną, którą zaimplementowałem:
function loadRoutes(folder){
if (!folder){
folder = __dirname + '/routes/';
}
fs.readdir(folder, function(err, files){
var l = files.length;
for (var i = 0; i < l; i++){
var file = files[i];
fs.stat(file, function(err, stat){
if (stat && stat.isDirectory()){
loadRoutes(folder + '/' + file + '/');
} else {
var dot = file.lastIndexOf('.');
if (file.substr(dot + 1) === 'js'){
var name = file.substr(0, dot);
// I'm also passing argv here (from optimist)
// so that I can easily enable debugging for all
// routes.
require(folder + name)(app, argv);
}
}
});
}
});
}
Moja struktura katalogów jest trochę inna. Zazwyczaj definiuję trasy w app.js (w katalogu głównym projektu) przez require
-ing './routes'
. W związku z tym pomijam czek, index.js
ponieważ ja chcę go również uwzględnić.
EDYCJA: Możesz również umieścić to w funkcji i wywołać rekurencyjnie (zredagowałem przykład, aby to pokazać), jeśli chcesz zagnieździć swoje trasy w folderach o dowolnej głębokości.
możesz umieścić wszystkie funkcje trasy w innych plikach (modułach) i połączyć je z plikiem głównego serwera. w głównym pliku ekspresowym dodaj funkcję, która połączy moduł z serwerem:
function link_routes(app, route_collection){
route_collection['get'].forEach(route => app.get(route.path, route.func));
route_collection['post'].forEach(route => app.post(route.path, route.func));
route_collection['delete'].forEach(route => app.delete(route.path, route.func));
route_collection['put'].forEach(route => app.put(route.path, route.func));
}
i wywołaj tę funkcję dla każdego modelu trasy:
link_routes(app, require('./login.js'))
w plikach modułu (na przykład - plik login.js) zdefiniuj funkcje jak zwykle:
const login_screen = (req, res) => {
res.sendFile(`${__dirname}/pages/login.html`);
};
const forgot_password = (req, res) => {
console.log('we will reset the password here')
}
i eksportujemy go za pomocą metody żądania jako klucza, a wartością jest tablica obiektów, każdy ze ścieżką i klawiszami funkcyjnymi.
module.exports = {
get: [{path:'/',func:login_screen}, {...} ],
post: [{path:'/login:forgotPassword', func:forgot_password}]
};