Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: create v2 Migration document #931

Merged
merged 13 commits into from
Mar 8, 2017
73 changes: 25 additions & 48 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ app.listen(3000);


## Middleware

Koa is a middleware framework that can take 3 different kinds of functions as middleware:

* common function
* async function
* generator function

Here is an example of logger middleware with each of the different functions:

Expand Down Expand Up @@ -78,69 +78,46 @@ app.use((ctx, next) => {
});
```

### GeneratorFunction

To use generator functions, you must use a wrapper such as [co](https://github.com/tj/co) that is no longer supplied with Koa.

```js
app.use(co.wrap(function *(ctx, next) {
const start = new Date();
yield next();
const ms = new Date() - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
}));
```

### Old signature middleware (v1.x) - Deprecated

**Old signature middleware (v1.x) support will be removed in v3**

Koa v2.x will try to convert legacy signature, generator middleware on `app.use`, using [koa-convert](https://github.com/koajs/convert).
It is however recommended that you choose to migrate all v1.x middleware as soon as possible.

```js
// Koa will convert
app.use(function *(next) {
const start = new Date();
yield next;
const ms = new Date() - start;
console.log(`${this.method} ${this.url} - ${ms}ms`);
});
```
### Koa v1.x Middleware Signature

You could do it manually as well, in which case Koa will not convert.
The middleware signature changed between v1.x and v2.x. The older signature is deprecated.

```js
const convert = require('koa-convert');
**Old signature middleware support will be removed in v3**

app.use(convert(function *(next) {
const start = new Date();
yield next;
const ms = new Date() - start;
console.log(`${this.method} ${this.url} - ${ms}ms`);
}));
```
Please see the [Migration Guide](docs/migration.md) for more information on upgrading from v1.x and
using v1.x middleware with v2.x.

## Babel setup

For Node 4.0+ and Babel 6.0 you can setup like this:
If you're not using `node v7.6+`, we recommend setting up `babel` with [`babel-preset-env`](https://github.com/babel/babel-preset-env):

```bash
$ npm install babel-register babel-plugin-transform-async-to-generator --save
$ npm install babel-register babel-preset-env --save
```

Setup `babel-register` in your entry file:

```js
// set babel in entry file
require('babel-register')({
plugins: ['transform-async-to-generator']
});
require('babel-register');
```

Check out an example in koa's [test](test/babel/index.js).
And have your `.babelrc` setup:

```json
{
"presets": [
["env", {
"targets": {
"node": true
}
}]
]
}
```

## Troubleshooting

Check the [Troubleshooting Guide](docs/troubleshooting.md) or [Debugging Koa](docs/guide.md#debugging-koa) in
Check the [Troubleshooting Guide](docs/troubleshooting.md) or [Debugging Koa](docs/guide.md#debugging-koa) in
the general Koa guide.

## Running tests
Expand Down
133 changes: 133 additions & 0 deletions docs/migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Migrating from Koa v1.x to v2.x

## New middleware signature

Koa v2 introduces a new signature for middleware.

**Old signature middleware (v1.x) support will be removed in v3**

The new middleware signature is:

```js
// 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!

The signature has changed to pass `Context` via an explicit parameter, `ctx` above, instead of via
`this`. The context passing change makes koa more compatible with es6 arrow functions, which capture `this`.

## Using v1.x Middleware in v2.x

Koa v2.x will try to convert legacy signature, generator middleware on `app.use`, using [koa-convert](https://github.com/koajs/convert).
It is however recommended that you choose to migrate all v1.x middleware as soon as possible.

```js
// Koa will convert
app.use(function *(next) {
const start = new Date();
yield next;
const ms = new Date() - start;
console.log(`${this.method} ${this.url} - ${ms}ms`);
});
```

You could do it manually as well, in which case Koa will not convert.

```js
const convert = require('koa-convert');

app.use(convert(function *(next) {
const start = new Date();
yield next;
const ms = new Date() - start;
console.log(`${this.method} ${this.url} - ${ms}ms`);
}));
```

## Upgrading middleware

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

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

Upgrading your middleware may require some work. 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


## 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`.

## Application object constructor requires new

In v1.x, the Application constructor function could be called directly, without `new` to
instantiate an instance of an application. For example:

```js
var koa = require('koa');
var app = module.exports = koa();
```

v2.x uses es6 classes which require the `new` keyword to be used.

```js
var koa = require('koa');
var app = module.exports = new koa();
```

## ENV specific logging behavior removed

An explicit check for the `test` environment was removed from error handling.

## Dependency changes

- [co](https://github.com/tj/co) is no longer bundled with Koa. Require or import it directly.
- [composition](https://github.com/thenables/composition) is no longer used and deprecated.

## v1.x support

The v1.x branch is still supported but should not receive feature updates. Except for this migration
guide, documentation will target the latest version.

## Help out

If you encounter migration related issues not covered by this migration guide, please consider
submitting a documentation pull request.
3 changes: 1 addition & 2 deletions lib/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ module.exports = class Application extends Emitter {
if (isGeneratorFunction(fn)) {
deprecate('Support for generators will be removed in v3. ' +
'See the documentation for examples of how to convert old middleware ' +
'https://github.com/koajs/koa/blob/master/Readme.md' +
'#old-signature-middleware-v1x---deprecated');
'https://github.com/koajs/koa/blob/master/docs/migration.md');
fn = convert(fn);
}
debug('use %s', fn._name || fn.name || '-');
Expand Down