欸 敌人们好啊
我是前端工作者B老师
刚刚有个前端小朋友问我,B老师产生什么事了?
我说怎么回事?给我发了几张截图,我一看
哦!
原来是昨天有几个小朋友在问egg.js怎么应用
他说要和我试试,我说能够
传统功夫是讲化劲儿的,四两拨千斤
二百多斤的英国大力士,都握不动我这一个手指

我一说他啪一下就站起来了,很快啊
而后上来就是,一个左正蹬,一个右鞭腿,一个左刺拳
我全副没防进来,被打当前天然是一起学习egg.js(局部内容来自egg.js官网)

我应用TypeScript创立egg.js

TypeScript

TypeScript 是 JavaScript 类型的超集,它能够编译成纯 JavaScript。

此前应用 TypeScript 开发 Egg ,会遇到一些影响 开发者体验 问题:

  • Egg 最精华的 Loader 主动加载机制,导致 TS 无奈动态剖析出局部依赖。
  • Config 主动合并机制下,如何在 config.{env}.js 外面批改插件提供的配置时,能校验并智能提醒?
  • 开发期须要独立开一个 tsc -w 独立过程来构建代码,带来临时文件地位纠结以及 npm scripts 复杂化。
  • 单元测试,覆盖率测试,线上谬误堆栈如何指向 TS 源文件,而不是编译后的 js 文件。

环境筹备

  • 操作系统:反对 macOS,Linux,Windows
  • 运行环境:倡议抉择 LTS 版本,最低要求 8.x。

疾速入门

通过骨架疾速初始化:

$ mkdir showcase && cd showcase
$ npm init egg --type=ts
$ npm i
$ npm run dev

目录标准

一些束缚:

  • Egg 目前没有打算应用 TS 重写。
  • Egg 以及它对应的插件,会提供对应的 index.d.ts 文件不便开发者应用。
  • TypeScript 只是其中一种社区实际,咱们通过工具链给予肯定水平的反对。
  • TypeScript 最低要求:版本 2.8。

整体目录构造上跟 Egg 一般我的项目没啥区别:

  • typescript 代码格调,后缀名为 ts
  • typings 目录用于搁置 d.ts 文件(大部分会主动生成)

showcase
├── app
│   ├── controller
│   │   └── home.ts
│   ├── service
│   │   └── news.ts
│   └── router.ts
├── config
│   ├── config.default.ts
│   ├── config.local.ts
│   ├── config.prod.ts
│   └── plugin.ts
├── test
│   └── */.test.ts
├── typings
│   └── */.d.ts
├── README.md
├── package.json
├── tsconfig.json
└── tslint.json

配置(Config)

Config 这块略微有点简单,因为要反对:

  • 在 Controller,Service 那边应用配置,需反对多级提醒,并主动关联。
  • Config 外部, config.view = {} 的写法,也应该反对提醒。
  • config.{env}.ts 里能够用到 config.default.ts 自定义配置的提醒。
import { EggAppConfig, EggAppInfo, PowerPartial } from "egg";export default (appInfo: EggAppInfo) => { const config = {} as PowerPartial<EggAppConfig>; // override config from framework / plugin // use for cookie sign key, should change to your own and keep security config.keys = appInfo.name + "_1606967424562_9661"; // add your egg config in here config.middleware = []; // add your special config in here const bizConfig = { sourceUrl: `https://github.com/eggjs/examples/tree/master/${appInfo.name}`, }; //连贯服务器 config.mysql = { //database configuration //单个数据源client //多个数据源clients clients: { db1: { //host host: "localhost", //port port: "3306", //username user: "root", //password password: "root", //database database: "egg", }, db2: { //host host: "localhost", //port port: "3306", //username user: "root", //password password: "root", //database database: "hubeiwh", }, }, // 所有数据库配置的默认值 default: {}, //load into app,default is open //加载到应用程序,默认为关上 app: true, //load into agent,default is close //加载到代理中,默认值为“敞开” agent: false, }; // the return config will combines to EggAppConfig return { ...config, ...bizConfig, };};

控制器(Controller)

// app/controller/home.tsimport { Controller } from "egg";export default class HomeController extends Controller { public async index() { const { ctx } = this; ctx.body = await ctx.service.test.sayHi("egg"); } public async user() { const { ctx } = this; ctx.body = await ctx.service.test.hello("locker"); } /** * 通过name字段查问egg库外面username表查问用户信息 */ public async name() { const { ctx } = this; const {name} =ctx.query; try { const user = await ctx.service.test.name(name); ctx.body = { code: 200, data: user, message: "success", }; } catch (e) { ctx.body = { code: 500, data: `user:${e}`, message: "error", }; } } /** * 通过entPid字段查问hubeiwh库外面cim_enterprise表查问用户信息 */ public async ent() { const { ctx } = this; const { entPid } =ctx.query; try { const res = await ctx.service.test.entprise(entPid); ctx.body = { code: 200, data: res, message: "success", }; } catch (e) { ctx.body = { code: 500, data: `user:${e}`, message: "error", }; } }}

路由(Router)

// app/router.tsimport { Application } from 'egg';export default (app: Application) => { const { controller, router } = app; router.get('/', controller.home.index); router.get('/user', controller.home.user); router.get('/name',controller.home.name); router.get('/ent',controller.home.ent);};

服务(Service)

// app/service/news.tsimport { Service } from "egg";/** * Test Service */export default class Test extends Service { /** * sayHi to you * @param name - your name */ public async sayHi(name: string) { return `hi, ${name}`; } public async hello(name: string) { return `你好, ${name}`; } /** * 查问egg库外面username表 * @param {string} name 用户名称 */ public async name(name: string) { const data: any = await this.app.mysql //应用db1数据库查问 .get("db1") .query(`SELECT * FROM USERNAME WHERE name = '${name}'`); return { data }; } /** * 查问hubeiwh库外面username表 * @param {number} entPid 企业id */ public async entprise(entPid: number) { const data: any = await this.app.mysql //应用db2数据库查问 .get("db2") .get("cim_enterprise", { enterpid: entPid }); return { data }; }}```