Express'te birden çok dosyaya rota işleyicileri nasıl dahil edilir?


223

Benim NodeJS expressuygulamamda app.jsbirkaç ortak rota var. Sonra birwf.js dosyada birkaç rota daha tanımlamak istiyorum.

Dosyada app.jstanımlanan diğer rota işleyicilerini nasıl tanıyabilirim wf.js?

Basit bir ihtiyaç işe yaramaz gibi görünüyor.


2
bu yanıtı kontrol edin stackoverflow.com/a/38718561/1153703
Bikesh M

Yanıtlar:


399

Eğer isterseniz ayrı bir dosyada yolları koymak , örneğin routes.js, oluşturabileceğiniz routes.jsbu şekilde dosyayı:

module.exports = function(app){

    app.get('/login', function(req, res){
        res.render('login', {
            title: 'Express Login'
        });
    });

    //other routes..
}

Ve sonra nesneyi bu şekilde app.jsgeçirmesini isteyebilirsiniz :app

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

Bu örneklere de bir göz atın

https://github.com/visionmedia/express/tree/master/examples/route-separation


18
Aslında, yazar (TJ Holowaychuck) daha iyi bir onay veriyor: vimeo.com/56166857
avetisk

Birden çok dosya için yönlendirme sorununu çözer, ancak app.js'de tanımlanan işlevlere yollardan erişilemez.
XIMRX

5
Bazı işlevlere ihtiyacınız varsa, bunları başka bir modüle / dosyaya koyun ve hem app.js hem de route.js'den talep edin
BFil

2
Her şeyin duyduğunu anladım ama ('./ route') (app) bu syntex aklımı uçurdu, kimse bana tam olarak bunun ne olduğunu söyleyebilir ya da geçen uygulama nesnesi "app" bildiğim kadarıyla bunun kullanımı nedir
ANinJa

6
Aşağıdaki bu soruya daha iyi bir cevap var - stackoverflow.com/a/37309212/297939
Dimitry

124

Bu daha eski bir soru olmasına rağmen burada benzer bir soruna çözüm bulmak için tökezledim. Buradaki çözümlerden bazılarını denedikten sonra farklı bir yöne gitmiştim ve çözümümü burada kalan herkes için ekleyeceğimi düşündüm.

Express 4.x'te yönlendirici nesnesinin bir örneğini alabilir ve daha fazla yol içeren başka bir dosyayı alabilirsiniz. Hatta yinelemeli olarak yapabilirsiniz, böylece rotalarınız diğer yolları içe aktarabilir ve bakımı kolay URL yolları oluşturmanıza olanak tanır. Örneğin, zaten '/ testler' uç noktam için ayrı bir rota dosyam varsa ve '/ testler / otomatik' için yeni bir rota kümesi eklemek istiyorsanız, bu '/ otomatik' rotaları başka bir dosyaya bölmek isteyebilirim '/ test' dosyamı küçük ve yönetilmesi kolay tut. Ayrıca, yolları gerçekten mantıklı bir şekilde URL yoluna göre gruplandırmanıza olanak tanır.

./App.js içeriği:

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 içeriği

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 içeriği:

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
Bu en iyi cevap, listenin başında olmalı! Teşekkür ederim
Kostanos

Js Rest API'si için bu yapıyı nasıl kullanabilirim?
MSM

@ MSMurugan yep u bu desenle bir dinlenme API'si oluşturabilirsiniz.
ShortRound1911

@ ShortRound1911 Ben bu desen bir dinlenme api inşa ve plesk hosting sunucusuna koymak, bir hata alıyorum
MSM

96

@ShadowCloud örneği üzerinde bina Ben bir alt dizine tüm yolları dinamik olarak dahil edebildi.

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

Ardından, rota dosyalarını route dizinine şu şekilde yerleştirin:

rotalar / test1.js

module.exports = function(app){

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

    //other routes..
}

Tekrarlayan o defalarca olarak ben nihayet sonra gerektiği gibi için app.js yerleştirilmesi

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

1
i bu yaklaşım daha iyi gibi, ana uygulama dosyasına özel bir şey eklemek zorunda kalmadan yeni yollar eklemenizi sağlar.
Jason Miesionczek

3
Güzel, ben swp dosyaları ile ilgili sorunlarla karşı karşıya olduğu gibi , dosya uzantısının ek bir kontrol ile , bu yaklaşımı da kullanın .
Geekfish

Ayrıca, w / bu ile readdirSync kullanmak zorunda değilsiniz, readdir iyi çalışıyor.
Paul

5
Bu yöntemi kullanarak, dizindeki dosyaları okumak için app.js dosyanızdaki yolları gerektirmek gibi bir ek yük var mı?
Abadaba

@Abadaba ile aynı şeyi bilmek istiyorum. Sunucuyu başlattığınızda veya her istekte bu ne zaman değerlendirilir?
imns

19

Ve önceki yanıtta daha fazla derleme yapın, route / index.js dosyasının bu sürümü .js (ve kendisi) ile bitmeyen dosyaları yok sayar.

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

Bunun için teşekkürler. Mac'te .DS_Storedosya ekleyen biri vardı ve her şeyi karıştırıyordu.
JayQuerie.com

19

Klasör .jsiçindeki tüm dosyaların tam özyinelemeli yönlendirmesi, bunu içine /routeskoyun 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

içinde /routessize koymak whatevername.jsve bu gibi yolları başlatmak:

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

Bu cevabı "ekspres" ile güncellemeye çalışıyorum: "^ 4.16.3". Bu cevap ShortRound1911 ile benzerdir.

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;

Umarım bu birine yardımcı olabilir. Mutlu kodlama!


8

Eğer kullanıyorsanız ekspres-4.x ile typescript ve ES6, bu kullanım için en iyi şablon olacaktır:

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

Kullanarak çok daha temizleyici varve module.exports.


5

Tüm bu cevaplara bir değişiklik:

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

Dizideki her dosyayı test ederek filtrelemek için bir normal ifade kullanın. Özyinelemeli değil, ancak .js ile bitmeyen klasörleri filtreleyecektir


5

Bunun eski bir soru olduğunu biliyorum, ama kendim gibi bir şey bulmaya çalışıyordum ve burası bittiğim yerdi, bu yüzden başka birinin aynı sorunları olması durumunda benzer bir soruna çözümümü koymak istedim. sahip m. Dışarıda konsinye denilen hoş bir düğüm modülü var sizin için görülen dosya sistemi şeyler bir sürü yapar (yani - hiçbir readdirSync şeyler). Örneğin:

Ben inşa etmeye çalışıyorum huzurlu bir API uygulaması var ve ben kimlik doğrulaması için '/ api / *' gitmek tüm istekleri koymak istiyorum ve ben kendi dizin içine api gitmek tüm yolları saklamak istiyorum (sadece 'api' diyelim). Uygulamanın ana bölümünde:

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

Yollar dizininin içinde "api" adında bir dizin ve api.js adında bir dosya var. Api.js'de, sadece:

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;

Her şey beklendiği gibi çalıştı. Umarım bu birine yardımcı olur.


5

Ayrı bir .js dosyasının rotalarınızı daha iyi organize etmesini istiyorsanız, app.jsdosyada dosya sistemindeki konumuna işaret eden bir değişken oluşturmanız yeterlidir:

var wf = require(./routes/wf);

sonra,

app.get('/wf', wf.foo );

Burada dosyanızda .foobazı işlevler belirtilir wf.js. Örneğin

// wf.js file 
exports.foo = function(req,res){

          console.log(` request object is ${req}, response object is ${res} `);

}

1
+1. Buradaki resmi örnekte gösterilen yaklaşım budur: github.com/strongloop/express/tree/master/examples/…
Matt Browne

1
Bu, app.js altındaki genel işlevleri ve değişkenleri paylaşmak için çalışıyor mu? Yoksa wf.foosunulan diğer çözümlerde olduğu gibi kapsam dışında oldukları için bunları vb. Ben normalde app.js ayrılmış değilse wf.foo paylaşılan değişkenlere / işlevlere erişeceğiniz durumda atıfta bulunuyorum.
David

evet, app.js'de 'foo' işlevini bildirirseniz app.get ('/ wf', foo); çalışacak
NiallJG


0

Bu muhtemelen şimdiye kadarki en harika yığın taşması sorusu / cevabıdır. Ben seviyorum Yukarıdaki Sam'in / Brad'in çözümler. Uyguladığım zaman uyumsuz sürümle karşılaşacağımı düşündüm:

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

Dizin yapım biraz farklı. Genellikle tarafından (projenin kök dizininde) app.js rotaları tanımlamak require-ing './routes'. Sonuç olarak, karşı çek atlıyorum index.jsçünkü istiyorum de dahil .

DÜZENLEME: Rotalarınızı rasgele derinlik klasörlerine yerleştirmek istiyorsanız, bunu bir işleve koyabilir ve yinelemeli olarak çağırabilirsiniz (bunu göstermek için örneği düzenledim).


2
Neden bir aysnc versiyonu istiyorsunuz? Muhtemelen trafiğe başlamadan önce tüm rotalarınızı ayarlamak istiyorsunuz, aksi takdirde bazı 'yanlış' 404'ler gönderebilirsiniz.
Joe Abrams

6
Aslında. Hala düğüm öğrenirken yazdım. Geçmişe baktığımda bunun mantıklı olmadığını kabul ediyorum.
tandrewnichols

0

tüm rota işlevlerini diğer dosyalara (modüller) koyabilir ve ana sunucu dosyasına bağlayabilirsiniz. ana ekspres dosyasında, modülü sunucuya bağlayacak bir işlev ekleyin:

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

ve her rota modeli için bu işlevi çağırın:

link_routes(app, require('./login.js'))

modül dosyalarında (örneğin - login.js dosyası), işlevleri her zamanki gibi tanımlayın:

const login_screen = (req, res) => {
    res.sendFile(`${__dirname}/pages/login.html`);
};

const forgot_password = (req, res) => {
    console.log('we will reset the password here')
}

ve bunu istek yöntemi ile anahtar olarak dışa aktarırsanız, değer her biri yol ve işlev tuşlarına sahip bir nesne dizisidir.

module.exports = {
   get: [{path:'/',func:login_screen}, {...} ],
   post: [{path:'/login:forgotPassword', func:forgot_password}]
};   
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.