Express에서 여러 파일에 라우트 핸들러를 포함시키는 방법은 무엇입니까?


223

내 NodeJS express응용 프로그램 app.js에는 몇 가지 공통 경로가 있습니다. 그런 다음 wf.js파일에서 몇 가지 경로를 더 정의하고 싶습니다.

파일에 app.js정의 된 다른 경로 처리기를 인식하려면 어떻게 wf.js해야합니까?

간단한 요구 가 작동하지 않는 것 같습니다.


2
이 답변을 확인하십시오 stackoverflow.com/a/38718561/1153703
Bikesh M

답변:


399

당신이하려는 경우 별도의 파일에 경로를 넣어 , 예를 들어 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


18
실제로 저자 (TJ Holowaychuck)가 더 나은 접근 방식을 제공합니다 : vimeo.com/56166857
avetisk

여러 파일의 라우팅 문제를 해결하지만 경로에서 app.js에 정의 된 함수에 액세스 할 수 없습니다.
XIMRX

5
일부 기능이 필요한 경우 다른 모듈 / 파일에 저장하고 app.js와 route.js 모두에서 필요로하는 기능
BFil

2
나는 모든 것을 듣고 이해하지만 ( './routes')(app)이 syntex가 내 마음을 아프게한다는 것을 이해했다.
ANinJa

6
아래에이 질문에 대한 더 나은 답변이 있습니다 — stackoverflow.com/a/37309212/297939
Dimitry

124

이것은 오래된 질문이지만 비슷한 문제에 대한 해결책을 찾기 위해 여기에서 우연히 발견되었습니다. 여기에 몇 가지 솔루션을 시도한 후에 다른 방향으로 가고 결국 여기에있는 다른 사람을 위해 솔루션을 추가 할 것이라고 생각했습니다.

express 4.x에서는 라우터 객체의 인스턴스를 가져와 더 많은 경로가 포함 된 다른 파일을 가져올 수 있습니다. 이 과정을 재귀 적으로 수행하여 경로가 다른 경로를 가져 와서 유지하기 쉬운 URL 경로를 만들 수 있습니다. 예를 들어, '/ tests'엔드 포인트에 대한 별도의 라우트 파일이 이미 있고 '/ tests / automated'에 대한 새로운 라우트 세트를 추가하려는 경우 이러한 '/ automated'라우트를 다른 파일로 분리 할 수 ​​있습니다. 내 '/ 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;

2
이것은 최고의 답변입니다. 목록의 맨 위에 있어야합니다! 감사합니다
Kostanos 2016 년

Node Js Rest API에이 구조를 사용할 수 있습니까?
MSM

@MSMurugan yep u는이 패턴으로 나머지 API를 만들 수 있습니다.
ShortRound1911

@ ShortRound1911 나는이 패턴을 휴식 API를 구축하고 플 리스크 호스팅 서버에 넣고, 오류가 발생합니다
MSM

96

@ShadowCloud의 예를 바탕으로 하위 디렉토리에 모든 경로를 동적으로 포함시킬 수있었습니다.

routes / 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);
    });
}

그런 다음 다음과 같이 경로 파일을 경로 디렉토리에 배치하십시오.

routes / test1.js

module.exports = function(app){

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

    //other routes..
}

필요에 따라 여러 번 반복 한 다음 마침내 app.js 배치

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

1
나는이 접근법을 더 좋아하고 주 앱 파일에 특정 항목을 추가하지 않고도 새로운 경로를 추가 할 수 있습니다.
Jason Miesionczek

3
좋습니다, swp 파일에 문제가 생겼을 때 파일 확장명추가로 확인 하면서이 방법도 사용합니다.
Geekfish

또한 readdirSync를 사용할 필요가 없으며 readdir이 제대로 작동합니다.
Paul

5
이 방법을 사용하여 디렉토리의 파일을 읽는 데 vs. app.js 파일의 경로가 필요한 오버 헤드가 있습니까?
Abadaba

@Abadaba와 같은 내용을 알고 싶습니다. 서버를 시작할 때 또는 모든 요청에 ​​대해 언제 평가됩니까?
imns

19

그리고 이전 답변에서 더 많은 것을 빌드하십시오.이 버전의 routes / 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);
    });
}

고마워 .DS_Store파일을 추가하는 Mac의 누군가가 있었고 모든 것을 망쳐 놓았습니다.
JayQuerie.com

19

폴더 .js안에 있는 모든 파일 의 전체 재귀 라우팅 ./routesapp.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' });
    });
}

8

이 답변을 "express": "^ 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;

이것이 누군가를 도울 수 있기를 바랍니다. 행복한 코딩!


8

TypeScript 및 ES6 과 함께 express-4.x 를 사용 하는 경우 다음이 사용 하기 가장 좋은 템플릿입니다.

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.


5

이 모든 답변을 한 번 조정하십시오.

var routes = fs.readdirSync('routes')
      .filter(function(v){
         return (/.js$/).test(v);
      });

배열의 각 파일을 테스트하여 정규식을 사용하여 필터링하십시오. 재귀는 아니지만 .js로 끝나지 않는 폴더를 필터링합니다.


5

나는 이것이 오래된 질문이라는 것을 알고 있지만, 나는 나 자신과 같은 것을 알아 내려고 노력하고 있었고 이것이 내가 끝낸 곳이므로 다른 누군가가 같은 문제가있는 경우 비슷한 문제에 대한 해결책을 제시하고 싶었다. 나는 가지고있다. consign 이라는 멋진 노드 모듈이 있습니다. (- 아니 readdirSync 물건 예) 당신을 위해 여기에 보여지는 파일 시스템 물건을 많이한다. 예를 들면 다음과 같습니다.

편안한 API 응용 프로그램을 만들고 있는데 '/ api / *'로 이동하는 모든 요청을 인증 받고 API에 들어가는 모든 경로를 자체 디렉토리에 저장하고 싶습니다. (단지 'api'라고합시다). 앱의 주요 부분에서 :

app.use('/api', [authenticationMiddlewareFunction], require('./routes/api'));

routes 디렉토리 안에는 "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;

모든 것이 예상대로 작동했습니다. 이것이 누군가를 돕기를 바랍니다.


5

별도의 .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} `);

}


1
app.js에서 전역 함수 및 변수를 공유하는 데 작동합니까? 아니면 wf.foo다른 제시된 솔루션과 같이 범위를 벗어 났기 때문에 등 으로 "전달"해야 합니까? app.js에서 분리되지 않은 경우 wf.foo의 공유 변수 / 함수에 일반적으로 액세스하는 경우를 언급하고 있습니다.
David

예. app.js에서 'foo'함수를 선언하면 app.get ( '/ wf', foo); 작동합니다
NiallJG


0

이것은 아마도 가장 멋진 스택 오버플로 질문 / 답변 일 것입니다. 나는 사랑 위 샘의 / 브래드의 솔루션을. 내가 구현 한 비동기 버전으로 차임 할 것이라고 생각했습니다.

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-ing 으로 경로를 정의 './routes'합니다. 결과적으로 그 검사도 포함 시키고 싶기index.js 때문에 검사를 건너 뜁니다 .

편집 : 임의의 깊이의 폴더에 경로를 중첩 시키려면 이것을 함수에 넣고 재귀 적으로 호출 할 수 있습니다 (이 예제를 편집했습니다).


2
aysnc 버전을 원하는 이유는 무엇입니까? 트래픽을 제공하기 전에 모든 경로를 설정하거나 'false'404를 보낼 수 있습니다.
Joe Abrams

6
과연. 나는 여전히 노드를 배우면서 그것을 썼습니다. 나는 그것이 이해가되지 않는다는 것에 동의합니다.
tandrewnichols

0

모든 라우트 기능을 다른 파일 (modules)에 넣고 기본 서버 파일에 링크 할 수 있습니다. 기본 Express 파일에서 모듈을 서버에 연결하는 함수를 추가하십시오.

   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}]
};   
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.