Expressの複数のファイルにルートハンドラーを含める方法


223

私のNodeJS expressアプリケーションにapp.jsは、いくつかの一般的なルートがあります。次に、wf.jsファイルでさらにいくつかのルートを定義します。

ファイルでapp.js定義されている他のルートハンドラーを認識するにはどうすればよいwf.jsですか?

単純なrequireは機能していないようです。


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 2014年

5
いくつかの機能が必要な場合は、それらを別のモジュール/ファイルに入れて、app.jsとroutes.jsの両方から必要とするだけです
BFil

2
私はすべてが聞こえることを理解しましたが、require( './ routes')(app)このシンテックスは私の心を吹き飛ばします
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
これがベストアンサーです。リストの一番上にしてください!ありがとう
コスタノス

Node Js Rest APIにこの構造を使用できますか?
MSM

@MSMuruganはい、このパターンでREST APIを構築できます。
ShortRound1911

@ ShortRound1911私はレストAPIをこのパターンで構築し、pleskホスティングサーバーに配置しています。エラーが発生します
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 2011

3
私もこの方法を使用しています。SWPファイルで問題が発生したため、ファイル拡張子さらにチェックします。
ギークフィッシュ

また、これと一緒にreaddirSyncを使用する必要はありません。readdirは正常に機能します。
ポール、

5
このメソッドを使用してディレクトリ内のファイルを読み取るのと、app.jsファイルでルートを要求するだけの場合のオーバーヘッドはありますか?
アバダバ2012年

@Abadabaと同じことも知りたいです。これはいつ評価されますか、サーバーを起動したとき、またはすべてのリクエストに対してですか?
imns 2013年

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

これをありがとう。Macで誰かが.DS_Storeファイルを追加していて、すべてが台無しになっていた。
JayQuerie.com

19

フォルダ.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' });
    });
}

8

この回答を「エクスプレス」で更新しようとしています:「^ 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

これらすべての答えを1つ微調整します。

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

正規表現を使用して、配列内の各ファイルをテストすることでフィルタリングします。再帰的ではありませんが、.jsで終わっていないフォルダを除外します


5

私はこれが古い質問であることを知っていますが、私は自分自身のようなものを理解しようとしていましたが、これが結局のところなので、他の誰かが同じ問題を抱えている場合に備えて、私の解決策を同様の問題に適用したいと思いましたmを持っています。呼ばれるそこに素敵なノードモジュールがあります委託( -なしreaddirSyncのものすなわち)あなたのためにここに見られるファイルシステムの多くのものを行います。例えば:

構築しようとしているRESTful 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;

すべてが期待どおりに機能しました。これが誰かを助けることを願っています。


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
+1。これはここに公式の例に示されているアプローチです:github.com/strongloop/express/tree/master/examples/...
マット・ブラウン

1
これはapp.jsでグローバル関数と変数を共有するために機能しますか?またはwf.foo、他の提示されたソリューションと同様に範囲外であるため、それらをなどに「渡す」必要がありますか?app.jsから分離されていない場合、通常はwf.fooの共有変数/関数にアクセスする場合を指します。
デビッド

はい、そうです。app.jsで 'foo'関数を宣言すると、app.get( '/ wf'、foo); 動作します
NiallJG 2016年


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 2013

0

すべてのルート関数を他のファイル(モジュール)に入れて、メインサーバーファイルにリンクできます。メインエクスプレスファイルに、モジュールをサーバーにリンクする関数を追加します。

   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.