koajs / koa-hbs

Handlebars templates for Koa.js
MIT License
160 stars 43 forks source link

Koa v2 #58

Closed chrisveness closed 7 years ago

chrisveness commented 7 years ago

With Node.js v7.0.0 out (with V8 5.4), it's now possible to run Koa v2 using async/await natively, without Babel (albeit behind a --harmony flag).

Would you be able to make a new version of koa-hbs available which will work with Koa v2? (published @next).

(I've tried getting the current koa-hbs working with Koa v2 using koa-adapter, but haven't succeeded).

shellscape commented 7 years ago

@chrisveness have you tried koa-convert? that's worked quite well for me.

koa v2 support is on the radar but I'm not personally planning to crank that out in the near term (one of the other devs in the org may, I can't speak to that). We'd be more than happy to take a look at a pull request though!

chrisveness commented 7 years ago

I'll give koa-convert a try. Wish I was up to offering a PR!

chrisveness commented 7 years ago

I'm still getting my head around promises, I think I'm not sufficiently up on generator functions et al to see what I should be doing with koa-convert. Could you give any steers on how I might be able to use koa-convert (or koa-adapter)?

I had hoped it might be as simple as the following, but of course not...

const Koa     = require('koa');          // @2.0.0
const router  = require('koa-router')(); // @7.0.0
const hbs     = require('koa-hbs');
const convert = require('koa-convert');

const app = new Koa();

app.use(convert(hbs.middleware({
    extname:   '.html',
    viewPath:    __dirname + '/',
})));

router.get('/', async function(ctx, next) {
    const context = { version: process.version, time: new Date() };
    console.log('router.get /', context);
    await ctx.render('hello-world', context);
});

app.use(router.routes());

app.listen(3000);
console.log('listening on 3000');

Otherwise I shall have to wait until you are able to implement Koa v2 support...

shellscape commented 7 years ago

Hm the result from hbs.middleware is exactly what koa-convert expects: https://github.com/gilt/koa-hbs/blob/master/index.js#L175

In what way does your code above fail?

chrisveness commented 7 years ago

Showing my ignorance here!

With the above code, I just get back a 404 'Not Found'. Not quite sure where that's being generated yet.

I think hbs.middleware() is fine, I think the issue is with render().

If I change the line

await ctx.render('hello-world', context);

to

ctx.render('hello-world', context).then(() => console.log('rendered'));

(which I think should work?) then I get TypeError: ctx.render(...).then is not a function thrown, which I guess means render() is not returning a promise, which I presume it needs to for await? Or perhaps there's an issue with the switch from this to ctx signature? Or have I got it completely wrong?

shellscape commented 7 years ago

I'll spin up a small project and see if I can reproduce at some point this weekend (no promises, big football weekend). that'll probably be needed for conversion for koa-hbs@next anyhow.

chrisveness commented 7 years ago

If it helps, I've put my test onto github, so you can use that as a starting point if you like.

git clone https://github.com/chrisveness/koa-hello-world.git

There are some notes in the README as to how to switch between the Koa v1 (working) and Koa v2 (failing) versions.

Thanks for looking into this (if you do get the chance) – and enjoy the football!

shellscape commented 7 years ago

@chrisveness OK the root cause of this is the await on ctx.render. That's awaiting a generator function, and it doesn't return properly. Working on a workaround in the meantime.

shellscape commented 7 years ago

@chrisveness here's the solution for koa2:

const convert = require('koa-convert');
const co      = require('co');

app.use(convert(hbs.middleware({
    extname:   '.html',
    viewPath:    __dirname + '/',
})));

app.use(async (ctx, next) => {
  const render = ctx.render;
  ctx.render = async function _convertedRender () {
    return co.call(ctx, render.apply(ctx, arguments))
  }
  await next();
});

router.get('/', async function(ctx, next) {
  const context = { version: process.version, time: new Date() };
  await ctx.render('hello-world', context);
});
shellscape commented 7 years ago

Updated the README to reflect our findings: https://github.com/gilt/koa-hbs#koa2

chrisveness commented 7 years ago

Thanks for that. With your ctx.render conversion middleware, my 'hello world' now works perfectly.

I'm now struggling with koa-compose before I venture into other areas such as partials... hopefully those will 'just work', or else I'll be able to work them out for myself.

Thanks for your help.

shellscape commented 7 years ago

No worries. If you run into another issue with the conversion, post a new issue. happy to help again

shellscape commented 7 years ago

koa-hbs@next has been published with full support https://github.com/gilt-labs/koa-hbs/tree/next