回顾一下之前的代码
===========

```typescript
import * as Koa from 'koa';
import * as Router from 'koa-router';

const app = new Koa;

const route = new Router;

route.get('/', async (ctx, next) => {
    ctx.body = 'hello ts-koa';
})

app.use(route.routes());

app.listen(3000, '127.0.0.1', () => {
    console.log('服务器在运行');
})
```
这样的代码是可以应付现在的开发场景的，但是我们是企业，企业网站不可能只有十来个路由，多的可以有上万个路由，如果都写在一个文件里，那肯定会乱七八糟。

我们最简单的做法就是把路由拆分到一个一个的文件里。

路由拆分第一个版本
===========
在src下新建一个router目录，用于存放我们的路由，在这里我们就新建一个叫做user.ts的路由吧。
```
.
├── dist
│   └── app.js
├── nodemon.json
├── package-lock.json
├── package.json
├── src
│   ├── app.ts
│   └── router        //新增
│       └── user.ts   //新增
└── tsconfig.json
```

我们的目录，变成了这样，我们书写一下user.ts

```js
//user.ts
export const user = async (ctx:any, next:any) => {
    ctx.body = 'hello ts-koa';
}
```

导出这个路由,我们回到app.ts
修改我们的代码，并且保存重启
```js
//app.js
import * as Koa from 'koa';
import * as Router from 'koa-router';
import { user } from './router/user';

const app = new Koa;

const route = new Router;

route.get('/', user);

app.use(route.routes());

app.listen(3000, '127.0.0.1', () => {
    console.log('服务器在运行');
})
```

到这里，我们将路由模块拆分出去了。有多少个路由，我们就在router中添加多少个路由。

不过好景不长，如果我们有1000个路由那么，app.ts还是会继续增大

```js 
import { user } from './router/user';
import ....
.....

route.get('/', user);
route.get('/', ...);
route.post('/', ...);

```
当我们新增一个路由模块的时候，就要来回的切换目录，先import再route搞一下，极其繁琐，而且重复。

我们必须解放我们的生产力：**自动扫描**


路由拆分第二个版本
===========

来回切换目录修改文件是极其繁琐和而且容易出错的，而且我们在某一个路由模块下，并不知道这个路由模块是什么http method的，很容易让我们摸不着头脑。

因此，我们引入框架第一个规范：

**使用 http method + 空格 + 路径作为key,方法作为导出的值**

具体看代码，修改user.ts：
```js
//user.ts
//user.ts
const user = async (ctx: any, next: any) => {
    ctx.body = 'hello user';
}

const userInfo = async (ctx: any, next: any) => {
    ctx.body = 'hello userinfo';
}

export default {
    'get /': user,
    'get /userinfo': userInfo
}
```

来到loader.ts,新增一下代码:
```ts
import * as fs from 'fs';
import * as Router from 'koa-router';

const route = new Router;

export function loader() {

    const dirs = fs.readdirSync(__dirname + '/router');

    dirs.forEach((filename) => {
        const mod = require(__dirname + '/router/' + filename).default;
        Object.keys(mod).map((key) => {
            const [method, path] = key.split(' ');
            const handler = mod[key];
            (<any>route)[method](path, handler);
        })
    })
    return route.routes();
}
```
这里的代码我稍微讲解一下，
主要是引入nodejs的``fs``模块进行目录的自动扫描，然后将扫描出来的结果用``require``导入，
最后通过切割我们导出时的``key``，拿到``http method 和 path``，把他们放进``koa-router``中。

route所提供的函数会有一大堆，如``route.get,route.patch,route.post``，这些方法都是**可索引的**，但是在ts中并不能。

值得注意的是```(<any>route)```是为了让``typescript``编译正确，我们将``route``强行断言为``any``类型，这样就不会报错了。




最后来到app.ts，修改代码：
```ts
//app.js
import * as Koa from 'koa';
import { loader } from './loader';

const app = new Koa;

app.use(loader());

app.listen(3000, '127.0.0.1', () => {
    console.log('服务器在运行');
})

```

保存，自动重启，由此，我们通过一个loader函数，封装了koa-router，我们的app启动变得清爽起来，这一堆的封装解决了：

- app启动变得干净无比，不再出现任何乱七八杂的路由
- loader模块自动加载所有的路由，我们想要增加路由就可以增加一个文件，然后按照我们的规范，导出就可以自动加载
- 不用再担心app.ts变长了，我们也可以在路由模块中直接看到我们的http method与路由的映射


到此，我们可以愉快的书写我们的逻辑了。

- 上一章：[自动编译Ts与自动重启](https://github.com/floveluy/Burnjs/blob/master/example/books/2.%E8%87%AA%E5%8A%A8%E7%BC%96%E8%AF%91ts%2B%E8%87%AA%E5%8A%A8%E9%87%8D%E5%90%AF.md)


- 下一章：[controller与service概念](https://github.com/floveluy/Burnjs/blob/master/example/books/4.%E5%BC%95%E5%85%A5controller%E4%B8%8Eservice%E6%A6%82%E5%BF%B5.md)

