Как включить обработчики маршрутов в несколько файлов в Express?
В моем NodeJS express
приложение у меня есть app.js
это имеет несколько общих маршрутов. Тогда в wf.js
Файл Я хотел бы определить еще несколько маршрутов.
Как я могу получить app.js
распознавать другие обработчики маршрутов, определенные в wf.js
файл?
Простое требование, похоже, не работает.
14 ответов
Если вы хотите поместить маршруты в отдельный файл, например routes.js
Вы можете создать routes.js
файл таким образом:
module.exports = function(app){
app.get('/login', function(req, res){
res.render('login', {
title: 'Express Login'
});
});
//other routes..
}
И тогда вы можете потребовать это от app.js
прохождение app
объект таким образом:
require('./routes')(app);
Посмотрите также на эти примеры
https://github.com/visionmedia/express/tree/master/examples/route-separation
Несмотря на то, что это старый вопрос, я наткнулся здесь на поиски решения аналогичной проблемы. Попробовав некоторые решения здесь, я в конечном итоге пошел в другом направлении и подумал, что добавлю свое решение для всех, кто окажется здесь.
В Express 4.x вы можете получить экземпляр объекта маршрутизатора и импортировать другой файл, который содержит больше маршрутов. Вы даже можете сделать это рекурсивно, чтобы ваши маршруты импортировали другие маршруты, позволяя вам создавать простые в обслуживании URL-пути. Например, если у меня уже есть отдельный файл маршрута для моей конечной точки / tests, и я хочу добавить новый набор маршрутов для / tests / automatic, я могу разбить эти / автоматизированные маршруты в другой файл для сохранить мой файл '/ test' небольшим и простым в управлении. Это также позволяет логически группировать маршруты по URL-пути, что может быть очень удобно.
Содержание./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);
Содержание./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;
Содержание./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;
Основываясь на примере @ShadowCloud, я смог динамически включить все маршруты в подкаталог.
маршруты /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);
});
}
Затем поместите файлы маршрутов в каталог маршрутов следующим образом:
маршруты /test1.js
module.exports = function(app){
app.get('/test1/', function(req, res){
//...
});
//other routes..
}
Повторяя это столько раз, сколько мне нужно, а затем, наконец, в app.js
require('./routes')(app);
Если вы используете Express-4.x с TypeScript и ES6, это будет лучший шаблон для использования;
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");
});
Гораздо яснее, скорее, используя var
а также module.exports
,
Полная рекурсивная маршрутизация всего .js
файлы внутри /routes
папку, поместите это в 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
в /routes
ты положил whatevername.js
и инициализируйте ваши маршруты следующим образом:
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' });
});
}
Более того, опираясь на предыдущий ответ, эта версия маршрутов /index.js будет игнорировать любые файлы, не заканчивающиеся на.js (и сам по себе)
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);
});
}
Я пытаюсь обновить этот ответ с "экспресс": "^4.16.3". Этот ответ похож на 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;
Я надеюсь, что это может кому-то помочь. Удачного кодирования!
Если вы хотите, чтобы отдельный файл.js лучше организовывал ваши маршруты, просто создайте переменную в app.js
файл, указывающий на его местоположение в файловой системе:
var wf = require(./routes/wf);
затем,
app.get('/wf', wf.foo );
где .foo
какая-то функция объявлена в вашем wf.js
файл. например
// wf.js file
exports.foo = function(req,res){
console.log(` request object is ${req}, response object is ${res} `);
}
Один твик ко всем этим ответам:
var routes = fs.readdirSync('routes')
.filter(function(v){
return (/.js$/).test(v);
});
Просто используйте регулярное выражение для фильтрации путем тестирования каждого файла в массиве. Это не рекурсивно, но оно отфильтровывает папки, которые не заканчиваются на.js
Я знаю, что это старый вопрос, но я пытался придумать что-то подобное для себя, и это место, в котором я оказался, поэтому я хотел найти решение аналогичной проблемы на случай, если у кого-то еще возникнут те же проблемы, что и у меня ". Я имею. Есть замечательный модуль для узлов, называемый consign, который делает много вещей из файловой системы, которые здесь видны для вас (то есть - без вещей readdirSync). Например:
У меня есть спокойное API-приложение, которое я пытаюсь создать, и я хочу поместить все запросы, которые идут в '/api/*', для аутентификации, и я хочу сохранить все свои маршруты, которые идут в api, в их собственный каталог (давайте просто назовем это "API"). В основной части приложения:
app.use('/api', [authenticationMiddlewareFunction], require('./routes/api'));
Внутри каталога маршрутов у меня есть каталог с именем "api" и файл с именем api.js. В api.js у меня просто есть:
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;
Все заработало как положено. Надеюсь, это кому-нибудь поможет.
index.js
const express = require("express");
const app = express();
const http = require('http');
const server = http.createServer(app).listen(3000);
const router = (global.router = (express.Router()));
app.use('/books', require('./routes/books'))
app.use('/users', require('./routes/users'))
app.use(router);
маршруты / users.js
const router = global.router
router.get('/', (req, res) => {
res.jsonp({name: 'John Smith'})
}
module.exports = router
маршруты / books.js
const router = global.router
router.get('/', (req, res) => {
res.jsonp({name: 'Dreams from My Father by Barack Obama'})
}
module.exports = router
если у вас есть локальный сервер (http: // localhost: 3000), тогда
// Users
curl --request GET 'localhost:3000/users' => {name: 'John Smith'}
// Books
curl --request GET 'localhost:3000/users' => {name: 'Dreams from My Father by Barack Obama'}
Я написал небольшой плагин для этого! надоело писать один и тот же код снова и снова.
https://www.npmjs.com/package/js-file-req
Надеюсь, поможет.
Это, возможно, самый удивительный вопрос / ответ (ы) о переполнении стека за всю историю. Я люблю решения Сэма / Брэда выше. Думал, что я буду взаимодействовать с асинхронной версией, которую я реализовал:
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);
}
}
});
}
});
}
Моя структура каталогов немного отличается. Обычно я определяю маршруты в app.js (в корневом каталоге проекта) require
-ную './routes'
, Следовательно, я пропускаю проверку против index.js
потому что я хочу включить это тоже.
РЕДАКТИРОВАТЬ: Вы также можете поместить это в функцию и вызывать ее рекурсивно (я отредактировал пример, чтобы показать это), если вы хотите вложить свои маршруты в папки произвольной глубины.
Вы можете поместить все функции маршрутизации в другие файлы (модули) и связать их с основным файлом сервера. в главном экспресс-файле добавьте функцию, которая свяжет модуль с сервером:
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));
}
и вызовите эту функцию для каждой модели маршрута:
link_routes(app, require('./login.js'))
в файлах модуля (например, в файле login.js) определите функции как обычно:
const login_screen = (req, res) => {
res.sendFile(`${__dirname}/pages/login.html`);
};
const forgot_password = (req, res) => {
console.log('we will reset the password here')
}
и экспортировать его с помощью метода запроса в качестве ключа, а значение представляет собой массив объектов, каждый из которых имеет путь и функциональные ключи.
module.exports = {
get: [{path:'/',func:login_screen}, {...} ],
post: [{path:'/login:forgotPassword', func:forgot_password}]
};