简体   繁体   中英

How to render template with Koa

My effort is to re-engineer my app from Express to Koa, so routes.js and controllers.js work previously. I try to create a small mechanism to render template in Koa. The goal is to apply the working code for other modules loading different template engines automatically through render variable calling module.view_engine per module.routes . Can you help?

+---modules
|   +---core
|   |   +---client
|   |   |   \---views
|   |   |           equipment.pug
|   |   |           error.pug
|   |   |           home.pug
|   |   |           
|   |   \---server
|   |       +---configs
|   |       |       core.config.json
|   |       |       core.koa.configs.js
|   |       |       
|   |       +---controllers
|   |       |       core.server.controllers.js
|   |       |       
|   |       +---models
|   |       |       assembly.server.model.js
|   |       |       ecms_equipment.server.model.js
|   |       |       ecms_location.server.model.js
|   |       |       ecms_main.server.model.js
|   |       |       index.js
|   |       |       
|   |       \---routes
|   |               core.server.routes.js
|   |               
|   +---assemblys
|   |   +---client
|   |   |   \---views
|   |   |           assembly_view.pug
|   |   |           
|   |   \---server
|   |       +---controllers
|   |       |       assemblys.server.controllers.js
|   |       |       
|   |       \---routes
|   |               assemblys.server.routes.js

That's my directory structure. With a couple of Lodash each loop, I am able to achieve view_path, routes, view_engine per module in core.koa.configs.js

modules[module] = {
    view_path: view_path,
    routes: routes,
    view_engine: view_engine
  };

In the same file, with module still inside the _.each loop, I call

// regex to narrow the scope of code experimenting
if (module.re('assemblys')) {
    // === var render here? ===
    require(routes)(app);
  }

That takes the app to the assembly.server.routes.js containing the following:

var controller  = require('../controllers/projects.server.controllers');


module.exports = function(app){
  app.get('/task', controller.assembly)
};

Then, in the assembly.server.controllers.js, I try to provide the assembly function but it doesn't work - 404 :

// load Sequelize models
var models = require( process.cwd() + '/modules/core/server/models');

exports.assembly = function *() {
  var that = this.body, views = require('co-views');
  var render = views('../../client/views/' , {
    map: {pug: 'jade'}
  });
  var Assembly = models.Assembly;

  Assembly.findAll().then(function (assemblys) {
    that = yield render('assembly_view' , {assemblys: assemblys});
  });
};

Previously, I put var render inside the core.configs to be able to use view_path right there but then when I pass render into function *() , I got error and app crash! When render was in core.configs, I had the routes.js file exporting this:

module.exports = function(app, render){
      app.get('/task', controller.assembly(render));
    };

Some Koa examples says using route in this app.use(route.get('/assembly', function *() { }); and I saw some other examples simply use this

app.get('/task', controller.assembly(render)); // cnpmjs.org, koan stack...

I prefer the latter. But having trouble with yield render and how to load app, render parameters into the function *(app,render) generator, I tried this but it doesn't work too. Error in stack trace.

The idea result is to have in core.koa.configs.js :

if (module.re('assemblys')) {
    var render = views(view_path , {
        map: view_engine
    });
    require(routes)(app, render);
}

then exporting routes

module.exports = function(app, render){
  app.get('/task', controller.assembly(render))
};

and the controller is able to render the assemblys:

exports.assembly = function *(render) {
  var that = this.body, views = require('co-views');
  var Assembly = models.Assembly;

  Assembly.findAll().then(function (assemblys) {
    that = yield render('assembly_view' , {assemblys: assemblys});
  });
};

Update: See stack-traces , see koa branch_commit . -compiled.js.map files were generated by ES6-Babel

Koa (unlike express) does not wait until you will set the response body. If your middleware function ended, and the response body is empty, it will give a 404 response. That's why, in koa you should avoid callbacks or promisify them.

Here is how your middleware function should look like in koa-style:

exports.assembly = function *(render) {
    var that = this.body, views = require('co-views');
    var Assembly = models.Assembly;

    var assemblys = yield Assembly.findAll();
    that = yield render('assembly_view' , {assemblys: assemblys});
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM