koajs / koa

Expressive middleware for node.js using ES2017 async functions

Home Page:https://koajs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Koa 2.0.0

jonathanong opened this issue · comments

Roadmap

We do not plan to release v2 as "stable" until async/await hits node.js. Requiring babel to run your server is just not good developer experience. I do this right now, and I run into a host of problems. Writing your middleware with just promises or with co() or Bluebird.coroutine() everywhere isn't a good experience either. The current way to write middleware is ideal until async/await is native.

You can track v8's progress on async functions here: https://bugs.chromium.org/p/v8/issues/detail?id=4483. After v8 implements async functions, it will take some time for that v8 version to hit stable (6 weeks i think, not sure), then more time for that v8 version to hit node stable (i believe they plan to release a major version every 6 months).

Thus, once async functions hit v8, we have between 2-7 months to release Koa v2 as stable, but it'll probably just take us a day since not much other than the middeware signature has changed.

Don't be scared to use Koa v2 Alpha right now, though. People are already using it in production, and we don't foresee any major changes until we mark it stable.

Changes

The new middleware signature is:

// uses async arrow functions
app.use(async (ctx, next) => {
  try {
    await next() // next is now a function
  } catch (err) {
    ctx.body = { message: err.message }
    ctx.status = err.status || 500
  }
})

app.use(async ctx => {
  const user = await User.getById(this.session.userid) // await instead of yield
  ctx.body = user // ctx instead of this
})

You don't have to use asynchronous functions - you just have to pass a function that returns a promise. A regular function that returns a promise works too!

We don't know how much performance difference there will be, nor do many of the maintainers really care. Koa is as minimal as a framework can be and will not be your app's bottleneck.

New Features

Hopefully, Koa v2 will not have any new features as new features can be added to v1 as well. The only new features that will be added to Koa v2 will be breaking changes. Some possible features are:

Features for HTTP2 support can still go into Koa v1. The only problem is that if it's not in require('http') or require('https'), we're not going to include it in Koa. node-spdy is probably going to be the code that is merged into node.js.

Middleware

All of the current stable versions of middleware should be targeting koa v1. If it doesn't, let us know and we'll fix it.

Middleware may have an "alpha" version of the koa v2 version. These should NOT be marked as stable. If they do not exist, let us know and we'll create an alpha version so you can try it with koa v2. Better yet, make a PR!

Upgrading Middleware

You will have to convert your generators to async functions with the new middleware signature:

app.use(async ctx => {
  const user = await Users.getById(this.session.user_id)
  ctx.body = { message: 'some message' }
})

Upgrading your middleware may be a pain in the ass. One migration path is to update them one-by-one.

  1. Wrap all your current middleware in koa-convert
  2. Test
  3. npm outdated to see which koa middleware is outdated
  4. Update one outdated middleware, remove using koa-convert
  5. Test
  6. Repeat steps 3-5 until you're done

We have plans to create a migration bot #625 to make this process slightly better.

Updating Your Code

You should start refactoring your code now to ease migrating to Koa v2:

  • Return promises everywhere!
  • Do not use yield*
  • Do not use yield {} or yield [].
    • Convert yield [] into yield Promise.all([])
    • Convert yield {} into yield Bluebird.props({})

You could also refactor your logic outside of Koa middleware functions. Create functions like function* someLogic(ctx) {} and call it in your middleware as const result = yield someLogic(this). Not using this will help migrations to the new middleware signature, which does not use this.

I currently use babel and use async functions + flow type outside of koa middleware. this will make my migration path in the future easier. I'm not sure if I plan to ever remove babel though since I really like flow type.

How You Can Help

  • Documentation - we need a lot!
  • Testing Koa v2 and its corresponding middleware
  • Help create the migration bot #625

Questions

  • Should we transpile w/ babel before we publish? It might make performance better as it transpiles down to ES5, which V8 is more optimized with. Anyone wanna try benchmarking it?

Should let user to do that, not koa itself.

@fengmk2 Maybe I'm missing something, but I don't think making the user transpile through Babel here is an adequate solution... wouldn't that require the user to modify what's in node_modules/ (/ fork koa and add babel transpiling in prepublish etc)?

Should we transpile w/ babel before we publish? It might make performance better as it transpiles down to ES5, which V8 is more optimized with. Anyone wanna try benchmarking it?
I think we should transpile for more reasons than performance (though that is a potential one). We can play with even more features this way, and there are quite useful / nice features in Babel that are hidden behind --harmony-x flags or entirely non-existent in Node 4.x.x.

yeah you can't expect users to transpile any of their node modules

Agreed. Personally, I think we should use Babel. Then, we don't require Node 4.x.x+ either- we just require an ES6 engine to use Koa (not to install / require etc) @jonathanong. Maybe not everyone is using Node 4.x.x because apps using Koa don't have to use a Node version that has any ES6 natively if we transpile, right? They could just be transpiling with Babel (or something else) themselves?

Basically, I think we should allow the user to decide how they want to run their app using our module. If we ship it as is without transpiling, then the user must use Node 4.x.x, but if we transpile and ship, they can use that, Babel, or something else- no restrictions as long as their engine is ES5+ and their application somehow supports ES6 (since generators). That is giving the user options.

But either way, asking users to transpile the module itself if they don't want to use Node 4.x.x isn't really reasonable (asking them to transpile it, that is. just saying only node 4.x.x is suboptimal, imo, but still reasonable).

I personally don't transpile. I can see the benefit, but in most case it just adds overhead for only a little benefit (code readability... which most dev don't need anyhow).

As far as I'm concerned, the 2.0 version should just be 4.x+ compatible, period. Devs can just stick with the 1.x branch for their existing applications. Everything is just fine. One of my project is still using a 0.21.0 version, and I don't see any reason to upgrade it. I started this project back when Node 0.11 was released, been using the --harmony flag then, and still using it with Node 0.12.7 at the moment.

Bottom line is, I don't see why 2.0 should be BC. I sure don't have any problem with it.

+1 for 4.x only. To me there's nothing overly compelling enough to really make anyone feel like they have to upgrade if they can't quite yet, just a signature change etc. If the perf thing proves out then maybe that'll be worth it, but still a little weird.

+1 to 4.x only too. with koa < 1.x people had to run recent/certain versions of node to have generators and that worked out alright/didn't seem to be an issue there.

+1 for 4.x only. koa is significant project which using new coming features to achieve great develop experience, so it needs move forward to the next steps.

@chentsulin Babel vs Node 4.x.x isn't about being able to use new features or not.

@tejasmanohar but support only Node 4.x.x will encourage people to upgrade, not just stay on 0.12. support from 0.x to 4 always be a nightmare to project maintainers. (maybe just like IE 6 ~ 11?)

If I does not use koa one year ago, I will stay on 0.10 for a long time.

@tejasmanohar what @chentsulin said is not really related to the use of Babel or not, but more about if Koa should be BC or not. My take is that, it should not and people should move forward.

That being said and in regards to the use of a transpiler, I don't like all the features in Babel... This is my choice, my opinion. I also do not use any project which are coded in CoffeeScript either. I may be an extremist on this matter, but I really don't like to have dependencies I don't really need nor use in my project. (And I have seen bugs and bad implementations being produced by transpilers that could have been trivial to avoid otherwise.)

My problem with using a transpiler is that it is opiniated. As everyone agree to be Node 4.x+ for version 2.0, all necessary optimizations are already there without using any development flags or a transpiler. As for code readability is concerned, there's not much Babel can add on top of that. Koa is supposed to be lightweight anyway. I haven't seen any valuable objective arguments to justify such dependency.

Ah, I see. Yeah, I don't think Koa 2.0 needs to be BC either.

+1 for Node 4.x requirement

+1 for Node 4.x requirement!

+1 for Node 4.x requirement.

Koa only works on node.js anyway, right? So it's not like other engines are at a loss. Any Node 4.x is LTS, so I'd expect people to be able to upgrade sooner or later.

I'm all for the node 4.x requirement, but I do have a note about babel compatibility:

I've been using the branch from #533 on a brand-new project over the past week, and I discovered that because it uses native, uncompiled es6, I had to be careful what babel transformers are used on my code. Just as one example, if the "es6.class" transformer is enabled (which isn't necessary in 4.x, but is nonetheless on by default) the Koa class can't be extended by babel-compiled code and throws compile-time errors.

This is really a babel issue if it's an issue at all, and I've opted to explicitly declare my transformations in my package.json to avoid it, but I'm sure others will encounter this use case.

These are my babel configs that work seamlessly with the latest Koa.

...
  "babel": {
    "whitelist": [
      "strict",
      "regenerator",
      "es6.modules",
      "es6.arrowFunctions",
      "es6.destructuring",
      "es6.spread",
      "es7.asyncFunctions"
    ]
  }
...

How is Babel currently being used in Koa? Why is it listed as a devDependency?

@yanickrochon I assume it's listed as a dev dependency because you need it (or another transpiler of sorts) to develop on the experimental portion with ES7 async functions and all that jazz. 🎶

That said, doesn't look like it's actually being used to transpile anything in the scripts etc but rather only in usage by a developer. Maybe @jonathanong can shed some light here?

oh yeah it was part of the experimental tests. i removed the tests in the async-function branch but not babel yet.

also, i'm not changing the stance on the node 4.x compatibility. i just know people care about performance and the usage of es6 features slows performance (due to VM not optimizing yet). using babel to transpile to ES5 may improve performance (as well as being very easy), but i would want to benchmark that before doing that.

Dev for 2.0 doesn't have to have an RC just yet and may as well be a proof of concept. Angular 2.0 has been in alpha for ages... lol... so Koa 2.0 doesn't have to be released next month. At some point, all these new ES6 features will be optimized.

Also, as a thought; is co still relevant, or will still be relevant in 2.0?

yeah we'll leave it in for now for function* (ctx, next) {} middleware. i don't see a reason not to unless anyone has objections.

Old middleware will not work anyway and will require koa-convert. I think we should remove co and instead let koa-convert take care of converting legacy, generator-based, context-as-this middleware. Might add performance, but the question should be why should we leave it in if old middleware won't work anyway.

Arrow functions are optimized in Node 4

should we remove co from koa, guys? this means that all your generator functions should look like this if you don't use babel:

app.use(co.wrap(function* (ctx, next) {
  yield next()
})

we're going to eventually remove co anyways... could be v2 or v3.

remove co after node LTS support async await ?

👍 for after Node LTS supports async/await

That's gonna be ages.

@felixfbecker Well, part of the question is would you rather use co#wrap. I'd guess 1.5 - 2 yrs till async/await is in Node LTS but may be completely wrong... all this Babel hype has made us immune to time!

I prefer to use Babel so I can choose between co or bluebird

There's already a proposal which I think have merits. Since co has been Promise-based for a while now, I think Koa should drop it as dependency and move to a Promise solution. The advantage of using promises is quite evident and should not have a negative impact in most cases. Also, old middlewares can use co.wrap if they need to be re-used, until they migrate to be 2.0 compatible. To me, since there is a solution that not only works but is clean means that there's no problem in dropping co in favour of Promise or async/await (using a transpiler for now).

Furthermore, Generators have always been "hacky". It does not promote good usage of the design pattern :)

@thelinuxlich

I prefer to use Babel so I can choose between co or bluebird

this should be irrelevant if you do app.use(function* (ctx, next) {}) right

@jonathanong how so? If I use async/await keywords I will need Babel anyway, right?

@jonathanong

  • Is function* (ctx, next) {} a valid middleware or just a shortcut for co.wrap(function* (ctx, next) {}) with app.use?
  • Should koa-compose and koa-router support it ?
  • Could koa-* middleware return function* (ctx, next) {} ?

I found some interesting things with koa-compose

e.g:

const middleware = compose([
  function *one(ctx, next) {
    // maybe will return something
  },
  function *two(ctx, next) {
    // maybe will return something
  }
])

// now, `yield middleware(ctx, next)` is a Promise Instance
app.use(function *(ctx, next) {
   const result = yield (yield middleware(ctx, next))
   // do something for result
})

Haven't been really following this discussion too much, but I feel like I'm missing the benefits of these changes. Is it just "new-ness"? The API seems more confusing now:

app.use((ctx, next) => {
  const start = new Date;
  return next().then(() => {
    const ms = new Date - start;
    console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
  });
});

Don't take this to sound negative, just curious for the reasoning behind these changes.

Hey @matthewmueller, it's taking advantage of the es7 syntax, which is much less of a hack than using generators:

app.use(async (ctx, next) => {
  const start = new Date;
  await next();
  const ms = new Date - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});

@mike-marcacci it should be async (ctx, next) => ...

correct :)

Mentioned somewhere else, but I think we should wait to upgrade middleware until async/await is native, otherwise we'll just be going through them all over again to upgrade. Plus doing it now is confusing in the sense that it makes it seem like people should be migrating, even though 2.0 is not a thing yet (IMO shouldn't be until async/await).

Other than async/await there's not really anything new, so the less pain for migration the better. Requiring Babel will just make Koa go vaporware, at least I certainly wouldn't want to use Babel for server code.

@tj I kinda agree with you that maybe v2 shouldn't be released as "stable" until async/await is in V8 if we've decided not to use Babel to transpile the module's code (though I think that's fine and means we can release v2 stable-y earlier)... reason for this is it's kind a regression to switch out promises / .then()ables for co / generators / yield since we lose the serially (top -> bottom) processed code /readability benefits for managing async flow that exist in v1.

UPDATE: basically, writing koa 2 middleware without async/await is harder, less readable, and a regression in terms of what co / koa v1 / yield provide- imo

commented

at least I certainly wouldn't want to use Babel for server code.

👍

I'd say on my end, I've made the updates I've submitted, since I made them locally to give it all a go - so may as well submit them.

Perhaps the middlewares/tooling which have released new versions (koajs/compose, koajs/rewrite, koajs/route) should unpublish the major bumps and republish with an -alpha suffix? If 2.0 is being tip-toed around for the time being then not much point in releasing them all as latest when koa itself hasn't done so.

Personally, I do prefer the promise interface, even without async/await (although obviously the new syntax will make it nicer to consume), just to remove confusion in thinking this is what generators "actually do".

I too understand the wait, but really like the Promise implementation. Did not like it at first, but really got to appreciate things like

function getSomeValue(key) {
  return valueCache[key] || (valueCache[key] = new Promise((resolve, reject) => {
    // do some async processing
    // then resolve(value); or reject(Error)
  }));
}

My question, however is: "What is the ETA for native async/await?" If the answer is "next year, or something", then we should really consider releasing Koa 3.0 then and start migrating essential middlewares right now. 😄

The tc39 page still has the spec in "DRAFT" but with the expectation that it will move to "FINISHED" this month.

Once it's finalized, it obviously has to be implemented in V8 before it can make its way to node, so the beginning of 2016 is the earliest I'd bet on.

fwiw, the arrow function spec did not move to stage 4 ("finished") this week - it's still stage 3.

@mike-marcacci Early 2016 seems a bit too hopeful.

@tejasmanohar, you're definitely right - just emphasizing that "next year, or something" is definitely the answer to @yanickrochon's question

Moreover, maybe it's just me, but I don't see how using co in Koa v1 is better than using Babel for async/await in Koa v2 (and official middleware). Someone explain?

If we don't use async/await through Babel in Koa v2 stuff, then what's the improvement to warrant a new version? Also, what are the real downsides of transpiling syntax on the server?

UPDATE: We don't have to use Babel or force anyone to use Babel in Koa itself but what about the official middleware. I don't see a reason not to use Babel there until async/await hits stable Node?

To me, the real improvement over co is stack trace. Just by replacing parts of my apps with promises made a real difference on maintenance cost.

As for Babel, AFAIC, this is just a matter of semantic as it really doesn't offer much than that. I personally don't care much about it. I also noticed that arrow functions are slightly slower than "legacy" functions, but I haven't really made a benchmark on that one.

Pff, forget the past, release Koa 2 now :)

I'm not concerned with the perf aspect of Babel or even using Babel in the core... it's more about whether or not to use Babel for async/await in official middleware in the Koa.js org. We should probably vote on a universal policy for this, as if we release Koa@2, users will expect the popular official middleware to be upgraded and follow a standard.

And, I'm not the only one noticing this... @coderhaoxin, @fengmk2, and @matthewmueller have all brought up concerns about the new Promise-based middleware in issues on other repos in the org. Without async/await, this feels like a regression of the async control flow benefits from Koa@1 with yield... almost feels like callbacks from a readability perspective. See here, here, and here.

So... I'll start the poll. +1 for Babel in official middleware for me. I don't wanna include Babel in the core or make users of Koa use Babel (like require hooks), but I think that's a fair, opinionated choice for the official middleware as they're merely clients of Koa 2, not Koa itself.

Could be a while before async/await is implemented in v8 (comment made 3 weeks ago):

I should also note that async is a particularly tricky feature that will require
deep knowledge of V8's innards. We expect this to be a multi-quarter project. In
particular, it ties in closely with generators, around which there currently are
various open questions in the V8 implementation. We have some plans for tackling
that next year, but not before we have finished ES6. To be honest, we would
prefer not to open that can right now, since ES6 already is producing a lot of
churn. - https://codereview.chromium.org/1423663006/

Here's a different issue on the same topic: https://code.google.com/p/v8/issues/detail?id=4483

commented

Hi,

I don't think you have to use babel on official middleware, unless thoses middleware are already es5 transpiled for end user. Users have to choose if they want async support with babel or use promise style as long as async has official support on node core.

Some people prefer use promise catch pattern than try/catch.

koa1: generator
koa2: promise ( async with babel)
koa3: native async

I think it's a not a bad idea to release a koa2

I think that requiring Babel will only cause harm to Koa as it should be a matter of choice for a project only. Forcing Babel (i.e. extra non essential dependencies) is a big 👎 for me.

As for promises regressing to a callback-like style, I disagree. The big issue with callbacks was the indentation problem, where the flow could easily get lost through the layers of callbacks, where people had to fragment code to keep it clean. With Promises, the control can easily be vertical and simple through chaining, and usually only require one level of indentation for many, many asynchronous requests within the same workflow. Hardly the same as with callbacks.

Also, the advantage of promises is the lack of try... catch in code (that I particularly find ugly) and is encapsulated in a more elegant way using promises.

My guess is that async/await will take a bit lot longer than a few months to implement (as suggested by @elgerlambert 's comment. The implementation will need to get around the stack trace problem that arise when using yield with co right now and produce a real call stack on error, among other things. Bottom line is, I would not be surprised to see this feature implemented only after the second quarter of 2016 in an unstable version of Node.

Thanks for the information guys. Yah, I think we should wait as well.

I'm -1 on the promise implementation (without await/async) for 2 reasons:

  1. It requires a change in all middleware (there are 1000's of koa middleware modules at this point, public and private)
  2. Aesthetically, I think it's really hard to say that the promise implementation is nicer than the generator implementation. There are more tokens and more indentation.

I agree with the others that I don't think it's reasonable to force everyone to use babel-node, it's also tangibly slower to recompile than node.

I do think the ctx stuff is nice, but I'd rather wait until async/await than force everyone to update their middleware twice.

Requiring end-users to transpile, and to transpile selected dependencies, is proper weird.

Publishing transpiled modules isnt a problem, then its just a matter of which coding style is preferred or performance. Of course, having a decent stack trace is necessary too.

If maintainers like the async/await style and it looks like (for the time being) es5 transpiled code would be most performant then surely pre-compilation is the way to go no? Just dont force that transpilation on to the end-user, who should be able to include a few middleware, attach them to koa and node server to get going.

async/await wouldn't force an additional iteration. The signature stays the same, so churning through all the middleware wouldn't have to happen again (though more complex middleware might opt to use the new syntax to simplify things).

I agree with the others that I don't think it's reasonable to force everyone to use babel-node, it's also tangibly slower to recompile than node.

If we transpile official middleware that's making use of async/await before publishing to NPM, the end user doesn't need to use Babel. Async/await are just handlers of promises. It's about what's used in the official middleware. @matthewmueller

I could live with middleware being developped with Babel (as a dev-dependency), and transpiled to ES2015 before being published to npm.

  • src the Babel implementation
  • dist the transpiled code

and refer to dist/*.js in package.json for the main module. Thus making middlewares ready for async/await while being available for Koa 2.

async/await wouldn't force an additional iteration

yah, the 2nd iteration is certainly optional, but people will probably want to upgrade their middleware again. i guess i just don't see any downside in waiting until async/await.

If we transpile official middleware that's making use of async/await before publishing to NPM, the end user doesn't need to use Babel. Async/await are just handlers of promises. It's about what's used in the official middleware.

just becomes harder to tweak and fix bugs you discover in your node modules, since it's compiled javascript. not as bad as coffeescript's compiled output, but still can be confusing.


Personally, I wouldn't mind supporting both promises and generators, but it seemed like folks wanted to support one or the other.

To prevent the need of an update when async/await is native and keep backward compatibility, the middlewares could be exported like this (assuming src contains the source and lib the transpiled code):

module.exports = asyncSupported() ? require('./src') : require('./lib');

+1 for what @targos said

-1 on babel forced for everybody.
+1 for releasing v2 with promise based middlewares. Fully agree with @menems .
Most of the middleware do not require processing before and after request at the same time, so the cases as @matthewmueller mentioned are few, and it will be just the replacement of yield* next with return next().
Project based middleware and request handling with Promises looks more structural either starting with

next()
.then(() => {
  // code
}).then(() => {

or ending

}).then(() => {
  // code
}).then(() => {
  return next()
});

I'm -1 on change middlewares that use lots of generator functions to promise implementation. Don't want to maintain tow different branches for all the middlewares. Actually our inner web framework are still base on koa 1.x until async/await is native, it is not friendly for koa's users to migrate at this stage.

Maybe we should set the latest tag to 1.x (and all the middlewares support koa@2 too) until we have a conclusion with this issue. IMO we should make sure most of the frequently-used middlewares are default to support koa@2(using async-await with babel or promise implementation) before we finally announce koa@2.

Replacing with promise-based ones seems really pointless to me since we'll just be doing it again later, back to the old yield code more or less. I don't see a huge reason to rush 2.0, I'd rather not taint the user experience and confuse people with something that isn't permanent. 2.0 has almost no new features, the reason for the bump was for async/await, so doing a 2.0 without async/await native is a bust IMO

+1. No point releasing 2.0 w/o async/await somehow (whether that's Babel, native, etc.). IMO- (Native async/await >) Babel async/await > Generators > Promise-based middleware w/o await.

yeah latest should be 1.x for a while. i haven't looked at how to publish "latest" on npm yet.

i don't see a rush with converting all the middleware to async/await or promises since you could always just use koa-convert or something. there's been a bunch of PRs but i've been more-or-less "meh" about them. some are fine since you don't NEED async functions to write it, but for others, it's easier to just use koa-convert.

With Koa 1.x, I get things like these

TypeError: You may only yield a function, promise, generator, array, or object, but the following object was passed: "undefined"
      at next (/home/yanick/dev/.../node_modules/koa/node_modules/co/index.js:101:25)
      at onFulfilled (/home/yanick/dev/.../node_modules/koa/node_modules/co/index.js:69:7)
      at process._tickDomainCallback (node.js:411:9)

I roughly have an idea where this is coming from, but it would make my life heck lot easier with a proper stack trace. If async/await doesn't get rid of that issue, screw that AFAIC.

I'll set my koa middlewares default to support koa 1.x, and a dist-tag koa2 point to the version that support koa 2.x.

$ npm view koa-bodyparser dist-tags
{ latest: '2.0.1', koa2: '3.0.0' }

Add some notifications in the readme, then change koa's latest tag to 1.x ?

doing a 2.0 without async/await native is a bust IMO

Agree.

Perhaps the middlewares/tooling which have released new versions (koajs/compose, koajs/rewrite, koajs/route) should unpublish the major bumps and republish with an -alpha suffix?

👍 @omsmith - except s/unpublish/deprecate

Yeah I'd be happy to republish to try not to confuse the ecosystem

On Sat, Nov 21, 2015 at 5:31 PM, Tejas Manohar notifications@github.com
wrote:

Perhaps the middlewares/tooling which have released new versions (koajs/compose, koajs/rewrite, koajs/route) should unpublish the major bumps and republish with an -alpha suffix?

👍 @omsmith - except s/unpublish/deprecate

Reply to this email directly or view it on GitHub:
#533 (comment)

Although, having said that surely a section at the top of the readme would suffice to explain which version hits which version of Koa

On Sat, Nov 21, 2015 at 5:33 PM, null matt@veryfizzyjelly.com wrote:

Yeah I'd be happy to republish to try not to confuse the ecosystem
On Sat, Nov 21, 2015 at 5:31 PM, Tejas Manohar notifications@github.com
wrote:

Perhaps the middlewares/tooling which have released new versions (koajs/compose, koajs/rewrite, koajs/route) should unpublish the major bumps and republish with an -alpha suffix?

👍 @omsmith - except s/unpublish/deprecate

Reply to this email directly or view it on GitHub:
#533 (comment)

No reason to rush this. As @tj said, there are very few actual improvements in Koa v2. If the overall consensus is no Babel for transpiling modules in this org (seems to be), then I vote we

  • Pause a Koa@2 release
  • Set Koa 1.x version as npm latest everywhere (in all Koajs/* middleware, too)
  • Move v2 to a non-master branch and put v1 on master (like Express).
    • This is because async/await is pretty far off from Node... First, it needs to be finalized in the ES2016 spec. Then, implemented in V8. Then... node. Would be surprised if it happened anytime before Q2 2016 (wild guess). Keeping v2 stuff on master for Koa + official middleware is confusing to newcomers, especially since the docs/ don't match up yet (which will obviously have to be fixed before we release v2 as well).
    • Add a notice to v1/master README about Koa 2
  • Start updating docs/ for Koa 2 on its non-master branch

Side note: I now see the -1 on Babel argument. One of the negative sides of Koa v1 pre-Node@4 was the requirement of using --harmony flags; we were longing for the features required to be in Node stable. Now that they are- if we introduce Babel and jump to async/await early, though we're not playing with as much risk as --harmony, it's still an extra step and yet another thing to push people away from using Koa in production. Koa v2 also provides no significant benefit to those who don't use async/await through Babel right now so transpiling doesn't solve much in the big picture.

I've upgraded a few projects from babel 5.x to 6.x mostly for performance issues, for a larger project initial load time took ~12s, not it takes ~4s. From my experience, introducing babel as a dependency is a terrible choice.

As mentioned above Generators have always been "hacky", well babel is a "hacky" choice as well, async/await are implemented using generators, so we only get a nicer syntax by introducing more complexity.

I agree with @tejasmanohar

commented

-1 on babel server code.

And I prefer this over ctx. I think we don't need to surrender to the arrow function. I use arrow function in small piece work, like Array.prototype.forEach / map , since it does not provide this binding, and our middlewares are not doing small piece work. So I don't use it in middlewares. that's it.

On that note, would someone with access to NPM please change @latest to koa v1.x? :)

$ npm -v
3.4.1

$ npm dist-tags ls koa
npm latest: 2.0.0-alpha.3

I've done this with koa-route. Ideally, as @stephenmathieson mentioned in koajs/route#42, you should be able to npm install koa koa-route (same for all other official middleware- I'll have a look through the rest of them I have access to later today).

// cc @jonathanong @tj @fengmk2 @dead-horse @juliangruber (just tagging the most active people from this thread that have access- for some reason, @koajs/owners doesn't work for me- guess only owners can do that.)

If we make a conclusion here, I'll make these changes later. any suggestions ?

  • create a branch v2.x from master.
  • set v1.x to default branch.
  • change latest tag in npm point to koa@1
  • make all the middlewares' latest tag support koa@1, and add a tag named koa2 to support koa@2.

👍 - thx, @dead-horse

My Votes-

  • create a branch v2.x from master.
  • set v1.x to default branch.
  • change latest tag in npm point to koa@1
  • make all the middlewares' latest tag support koa@1, and add a tag named koa2 to support koa@2.

Additions -

  • set v1.x code to master
  • make all middleware's master reflect version compatible with koa v1.x

Questions-

  1. Why do you prefer setting v1.x to default branch to just moving v1.x code to master? This is nicer, as most people assume master reflects the current stable ("latest") afaik.

UPDATE: I guess ^ is valid if you want to avoid rewriting git history. Yeah... probably best.

Everyone else- please vote 😄

Or create next tag for koa v2.x on npm.

I wondered the same thing about 2.0 being master.... it should've been a next branch with a 2.0-alpha* tags all along.

I'm cool w/ next branch

+1 for master being v1.x right now, next branch being created for v2.x, and using tags for actual version numbers, from either branch.

thanks for knocking this out, @dead-horse.

next question- should we continue accepting PRs for making official middleware v1 -> v2? I think it's a waste of a release for even the middleware (not sure koa core) until we have async/await. we'll have to update this all again once await is out, document this without await, and manage issues with/without await and for v1 until v2 is released stable and decently adopted. premature, imo.

My take on this is that some middleware can upgrade easily to Koa 2. Some of them do not rely on any asynchronous call, and having them compatible without koa-convert is just fine right now.

No need to wait for async/await if the middleware doesn't even need it. Besides, I personally prefer a Promise implementation as it does not force me to use await all the way down a function stack.

@yanickrochon Whether you use await or async is irrelevant, since they're just sugar for nested Promise thens and a Promise-returning function, respectively. If you're using Promises, you're compatible with others' use of async/await. If you're using async functions, you're compatible with others' use of Promises. This seems like it's solely a question of whether the project should use babel to transpile a specific kind of syntax sugar for Promises, a decision which has no impact on consumers of the project.

What's the status on koa 2 being stable?

it's pretty stable... you're free to use it and report any bugs to us.

we're just not in a rush to release it and update all the middleware until async functions are native in v8

I figured it was. I am using it now with babel, but I'm only using
promises. Think I should go back to 1.x or stay on 2.0?

On Thu, Dec 3, 2015 at 3:01 PM jongleberry notifications@github.com wrote:

it's pretty stable... you're free to use it and report any bugs to us.

we're just not in a rush to release it until async functions are native in
v8


Reply to this email directly or view it on GitHub
#533 (comment).

totally up to you :) i'm sticking with 1.x until i have time to update my middleware, though it could be as simple as wrapping every middleware with koa-convert

For what it's worth I'm using it with async and babel in a live (but only internal) project. Babel's a pain in the ass but if your team is comfortable working with it (ie, it's already part of your front-end development efforts) then you'll be fine on 2.0.

However, if you're looking to introduce these new features to a team that's unfamiliar with the extra step, or if you already depend on a lot of existing koa middleware, I'd recommend sticking to 1.x.

@mike-marcacci I've had zero problems with babel, but that's a discussion for another thread :) the thing we should all worry about is using something that will not actually become a standard.

We're using v2 on a number of internal projects and will probably roll it into client work early next year.

They are small services and we have a team used to the Babel transpile step on the client so that awkward step isn't a problem for us. Some of our common modules are already promise based so from that point v2 makes perfect sense for us. 

Haven't encountered any major problems from using it, and it's been very easy for less experienced devs to pick up and help create cracking services which is a nice bonus.

On Thu, Dec 3, 2015 at 8:13 PM, Mike Marcacci notifications@github.com
wrote:

For what it's worth I'm using it with async and babel in a live (but only internal) project. Babel's a pain in the ass but if your team is comfortable working with it (ie, it's already part of your front-end development efforts) then you'll be fine on 2.0.

However, if you're looking to introduce these new features to a team that's unfamiliar with the extra step, or if you already depend on a lot of existing koa middleware, I'd recommend sticking to 1.x.

Reply to this email directly or view it on GitHub:
#533 (comment)

I wouldn't be too worried about the stability too much here: Koa 2.0-alpha doesn't really bring any feature changes, just interface changes. If another drastic change makes its way into the "production-ready" 2.0 version of Koa, upgrading your app from 2.0-alpha wouldn't be substantially different from upgrading a 1.x app.

I personally find it quite sad that everyone want to stick with yield... oh, sorry, await (i.e. yield wrapped in ES6 syntax). The great advantage of using Promise is that you don't need to specify if a function is async or not; you just return a Promise if it is, or whatever otherwise. I often found myself requiring to make functions async just because, down in my call stack, some function was async... This is totally unnecessary with promises.

A few months ago, I saw a lot of Promise advocates, but they are somehow quiet nowadays.

@yanickrochon an async function is just one that statically returns a Promise. it's not about "needing" to specify, it's about "getting" to - since everything should return one anyways, to make future sync/async refactors a nonbreaking change.

Well, I'm not 100% sure I agree with the "everything should be a promise" prescription... but to correct your point @yanickrochon, you don't need to make a function async just because it calls one... an async function simply returns a promise; when you return inside your async function, it resolves the promise with the return value. Functions b and c are equivalent:

async function a() {
    return 'a';
}

async function b() {
    var r = await a();
    return r + 'b';
}

function c() {
    return a().then(function(r) {
        return r + 'b';
    });
}

@mike-marcacci can you call b in a function that is not declared as async? Or is it required to have all the functions in the call stack to be declared as such?

In the case of c, the caller is not required to be async (i.e. it can call c() and simply ignore it's returned value).

Like he noted, async functions just return promises.

function d() {
  return (Math.random() % 2 ? b : c)().then (r => r + 'c');
}