【问题标题】:How can I split my koa routes into separate files?如何将我的 koa 路由拆分为单独的文件?
【发布时间】:2015-07-28 22:09:51
【问题描述】:

我正在尝试弄清楚如何将我的路线拆分为单独的文件。

到目前为止,我有这个,但它不起作用。当我尝试访问 http://localhost:3001/api/things 时,我只得到 Not found

//server.js
var koa = require('koa');
var app = koa();
var router = require('koa-router');

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


// routes.js
module.exports = function *(app){
  app.use('/api/things', require('./api/things'));
};


// api/things/index.js

var Router = require('koa-router');
var router = new Router({
  prefix: '/api/things'
});

router.get('/', function *(){
  this.body = [{ name: 'Foo'}, { name: 'Bar' }];
});

module.exports = router;

【问题讨论】:

  • 嗨,如果您仍然活跃,您可以更改接受的答案吗?给获得 47 票的那一位。

标签: node.js koa koa-router


【解决方案1】:

编辑:我更新了下面的代码示例,因为 npm 上的 koa-router 包不再维护。 Koa 团队以 @koa/router 的名义对其进行了官方分叉。


对于任何阅读本文并对如何在 Koa 2.X 中执行此操作感到好奇的人:

app.js

import Koa from 'koa'
import rootRouter from './routes/root'
import userRouter from './routes/user'

const app = new Koa()

app.use(rootRouter.routes())
app.use(rootRouter.allowedMethods())
app.use(userRouter.routes())
app.use(userRouter.allowedMethods())

export default app

routes/root.js

import Router from '@koa/router'
const router = new Router()

router.get('/', async (ctx, next) => {
  ctx.body = 'Hello'
})

export default router

routes/user.js

import Router from '@koa/router'
const router = new Router({ prefix: '/user' })

router.get('/', async (ctx, next) => {
  ctx.body = 'Some User'
})

export default router

如果要避免routes()allowedMethods()的重复,可以使用koa-compose组合中间件。为简单起见,我在它周围做了一个wrapper 以简化koa-router 的使用。使用它看起来像这样:

app.js

import Koa from 'koa'
import router from './routes'

const app = new Koa()

app.use(router())

export default app  

routes/index.js

import combineRouters from 'koa-combine-routers'
import rootRouter from './root'
import userRouter from './user'

const router = combineRouters(
  rootRouter,
  userRouter
)

export default router

它也会做同样的事情。

【讨论】:

  • 我已经尝试过这个解决方案,但我遇到了下一个错误:未定义路由器。
  • @nole。你有可以与GitHub gist 之类的东西分享的代码示例吗?
【解决方案2】:

server.js

var app = require('koa')();
var router = require('./routes');
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000);

routes.js

var router = require('koa-router')();
router.get('/', function* () {
    this.body = 'router test';
});
module.exports = router;

【讨论】:

    【解决方案3】:

    这样的事情应该可以工作:

    // app.js
    var koa = require('koa'),
        app = koa();
    
    require('./routes1')(app);
    require('./routes2')(app);
    
    app.listen(3000);
    
    // routes1.js
    var Router = require('koa-router');
    function register (app) {
      var router = new Router({
        prefix: '/api'
      });
      router.get('/', ...); // responds to "/api"
      router.get('/messages', ...); // responds to "/api/messages"
      app.use(router.routes());
      app.use(router.allowedMethods());
    }
    
    module.exports = register
    
    // routes2.js
    var Router = require('koa-router');
    function register (app) {
      var router = new Router();
      router.get('/', ...); // responds to "/"
      app.use(router.routes());
      app.use(router.allowedMethods());
    }
    
    module.exports = register
    

    【讨论】:

    • allowedMethods() 调用的目的是什么?
    • 支持 http OPTIONS 方法并响应如下: 200 OK Allow: HEAD,GET,PUT,DELETE,OPTIONS 本质上指定服务器对给定 URL 支持的方法
    • 这是一个很好的解决方案,但它现在已经过时并且无法使用。
    • 我忘记了细节。这是一个旧帖子。我相信 koa 或 koa-router 有一个重大更新,改变了语法。我最终需要执行以下操作: var api = new Router(); var api1 = require('./methods/api1'); api.use('/api1/v0/', api1.routes(), api1.allowedMethods()); var api2 = require('./methods/api2'); api.use('/api2/v0/', api2.routes(), api2.allowedMethods()); app.use(api.routes());
    【解决方案4】:

    对于 Koa 2.x,我发现 嵌套路由 带有 前缀 来交付货物,没有额外的包裹。

    假设 /api/dogs/api/cats 是必需的结果。

    像这样:

    app.js

    import Koa from 'koa';
    import Router from 'koa-router';
    import apiRouter from './routes/apiRouter';
    
    const app = new Koa();
    
    app.use(apiRouter.routes(), apiRouter.allowedMethods());
    
    app.listen(3000);
    
    export default app;
    

    routes/apiRouter.js

    import Router from 'koa-router'
    
    import dogsRouter from './dogsRouter'
    import catsRouter from './catsRouter'
    
    const apiRouter = new Router({ prefix: '/api' })
    
    const nestedRoutes = [dogsRouter, catsRouter]
    for (var router of nestedRoutes) {
        apiRouter.use(router.routes(), router.allowedMethods())
    }
    
    export default apiRouter;
    

    routes/dogsRouter.js

    import Router from 'koa-router'
    
    const dogsRouter = new Router({ prefix: '/dogs' });
    
    dogsRouter.get('/', async (ctx, next) => {
      ctx.body = 'Dogs be here'
    });
    
    export default dogsRouter;
    

    routes/catsRou​​ter.js

    import Router from 'koa-router'
    
    const catsRouter = new Router({ prefix: '/cats' });
    
    catsRouter.get('/', async (ctx, next) => {
      ctx.body = 'Cats be here'
    });
    
    export default catsRouter;
    

    【讨论】:

      【解决方案5】:

      我认为 TJ 在他这样做时牢记在心的简约方法

      koa、koa-route、koa-mount

      采用您喜欢的方式安装的小型独立应用程序:

      index.js

      var app = require('./app')
      app.listen(3000);
      

      app.js

      const Koa = require('koa')
      const _ = require('koa-route')
      const mount = require('koa-mount')
      const app = new Koa()
      const pets = require('./pets')
      
      // sub apps
      app.use(mount('/pets', pets))
      
      // root app
      app.use(_.get('/', function(){
        this.body = "hello";
      }))
      
      module.exports = app;
      

      pets.js

      var Koa = require('koa');
      var _ = require('koa-route');
      var app = new Koa();
      
      
      app.use(_.get('/', ctx => ctx.body = "pets" ));
      app.use(_.get('/:name', (ctx, name) => ctx.body = "pet: "+ name));
      
      module.exports = app;
      

      【讨论】:

        【解决方案6】:

        这就是我最终的结果:

        //server.js
        'use strict';
        
        var koa = require('koa');
        var app = koa();
        var serve = require('koa-static');
        var path = require('path');
        var router = require('koa-router');
        var cfg = require('./config');
        var mw = require('./middleware');
        
        app.use(serve(path.resolve(__dirname, '../client')));
        app.use(mw.requestTime('Response-time'));
        app.use(router(app));
        app.use(cfg.db.connect);
        
        require('./routes')(app);
        
        app.get('/api', function *(){
          this.body = 'Welcome to API v1';
        });
        
        app.use(cfg.db.close);
        app.listen(cfg.env.port);
        
        
        
        //routes.js
        module.exports = function (app){
          app.use(require('./api/things').routes());
        };
        
        
        // api/things/index.js
        var Router = require('koa-router');
        
        var router = new Router({
          prefix: '/api/things'
        });
        
        var ctrl = require('./controllers');
        
        router.get('/', ctrl.list);
        router.get('/:id', ctrl.get);
        router.post('/', ctrl.post);
        router.put('/:id', ctrl.put);
        router.del('/:id', ctrl.del);
        
        module.exports = router;
        
        
        // api/things/controllers.js
        
        var r = require('rethinkdb');
        var http = require('http');
        var parse = require('co-body');
        var ctrl = module.exports = {};
        
        ctrl.list = function *(next){
        };
        
        ctrl.get = function *(next){
        };
        
        ctrl.post = function *(next){
        };
        
        ctrl.put = function *(next){
        };
        
        ctrl.del = function *(next){
        };
        

        【讨论】:

          【解决方案7】:

          您可以将所有路由放在一个名为 routes 的文件夹中,然后遍历该文件夹中的所有文件,请求它们并初始化。这样,对于任何新路线,只需在路线文件夹中创建一个文件即可。

          所以是这样的:

          index.js

          const Koa = require("koa");
          const logger = require("koa-logger");
          const bodyParser = require("koa-bodyparser");
          
          const app = new Koa();
          
          app.use(logger());
          app.use(bodyParser());
          
          require("./routes")(app);
          
          const server = app.listen(config.server.port);
          
          module.exports = server;
          

          /routes/index.js

          const fs = require("fs");
          const path = require("path");
          const baseName = path.basename(module.filename);
          
          const routes = fs
              .readdirSync(path.join(__dirname))
              .filter(
                  file =>
                      file.indexOf(".") !== 0 &&
                      file !== baseName &&
                      file.slice(-3) === ".js"
              )
              .map(file => require(path.join(__dirname, file)));
          
          module.exports = function(app) {
              for (var router of routes) {
                  app.use(router.routes());
              }
          };
          

          然后在您想要的 /routes 文件夹中

          /routes/user.js

          /routes/customer.js

          都是路由器出口,比如

          /routes/auth.js

          const Router = require("koa-router");
          const authControllers = require("../controllers/auth");
          
          const {
              jwtAuth,
              login,
              register,
              forgotPassword,
              resetPassword,
              getAuthenticatedUser
          } = authControllers;
          
          const router = new Router({ prefix: "/auth" });
          
          router.post("/register", register);
          router.post("/login", login);
          router.post("/forgot-password", forgotPassword);
          router.post("/reset-password/:resetToken", resetPassword);
          router.get("/profile", jwtAuth, getAuthenticatedUser);
          
          module.exports = router;
          

          【讨论】:

          • 我不知道为什么这个答案被低估了。这通常可以在大型应用程序中使用以省略冗余。简单并遵循 DRY 原则。谢谢@Goran。您介意分享任何其他构建大型 Koa 应用的技巧吗?
          【解决方案8】:

          类似,但正是我需要的是:

          app.js

          "use strict";
          import Koa from 'koa';
          const app = new Koa();
          
          import Router from 'koa-router';
          const router = new Router();
          
          import mount from 'koa-mount';
          import routes from "./router/index.mjs";
          
          app.use(mount(routes));
          app.use(router.routes());
          
          app.listen(3000, () => console.log("Listening on port: 3000"));

          路由器/index.mjs

          "use strict";
          import Koa from 'koa';
          const app = new Koa();
          
          import Router from 'koa-router';
          const router = new Router();
          
          router.get('/', async (ctx, next) => {
              ctx.body = {success: true};
              await next();
          });
          
          app.use(router.routes());
          
          export default app;

          【讨论】:

            猜你喜欢
            • 2018-06-24
            • 1970-01-01
            • 1970-01-01
            • 2023-03-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多