博客
关于我
使用typescript改造koa开发框架
阅读量:420 次
发布时间:2019-03-06

本文共 4814 字,大约阅读时间需要 16 分钟。

Koa 项目脚手架改造

项目开发环境搭建

基于 gulp 搭建开发编译环境,使用 gulp-typescript 编译 TypeScript 文件,gulp-nodemon 监控文件变更,自动编译并重启 Node 服务,提升开发效率。

gulp 配置

const { src, dest, watch, series, task } = require('gulp');
const del = require('del');
const ts = require('gulp-typescript');
const nodemon = require('gulp-nodemon');
const tsProject = ts.createProject('tsconfig.json');
function clean(cb) {
return del(['dist'], cb);
}
function toJs() {
return src('src/**/*.ts')
.pipe(tsProject())
.pipe(dest('dist'));
}
function runNodemon() {
nodemon({
inspect: true,
script: 'src/app.ts',
watch: ['src'],
ext: 'ts',
env: { NODE_ENV: 'development' },
}).on('crash', () => {
console.error('Application has crashed!');
});
}
const build = series(clean, toJs);
task('build', build);
exports.build = build;
exports.default = runNodemon;

TypeScript 配置

{
"compilerOptions": {
"baseUrl": ".",
"outDir": "./dist",
"module": "commonjs",
"target": "esnext",
"allowSyntheticDefaultImports": true,
"importHelpers": true,
"strict": false,
"moduleResolution": "node",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedParameters": true,
"noUnusedLocals": true,
"noImplicitReturns": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"allowJs": true,
"sourceMap": true,
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}

ESLint 配置

{
"env": {
"es6": true,
"node": true
},
"extends": [
"eslint:recommended",
"@typescript-eslint/eslint-recommended"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"rules": {
"indent": ["warn", 2],
"no-unused-vars": 0
}
}

package.json 运行配置

{
"scripts": {
"start": "gulp", // 开发模式
"build": "gulp build", // 生产模式
"eslint": "eslint --fix --ext .js,.ts src/", // 格式化代码
"server": "NODE_ENV=production && node dist/app" // 生成生产服务器
}
}

添加类型化支持

项目主要使用以下组件:

  • jsonwebtoken
  • Koa
  • koa-body
  • koa-compress
  • koa-favicon
  • koa-logger
  • koa-router
  • koa-static
  • koa2-cors
  • log4js
  • Node

安装对应的类型定义文件:

npm install -D @types/jsonwebtoken @types/koa @types/koa-compress @types/koa-favicon @types/koa-logger @types/koa-router @types/koa-static @types/koa2-cors @types/log4js @types/node

使用 TypeScript 装饰器改造项目

定义 HTTP 请求的装饰器

import 'reflect-metadata';
import { ROUTER_MAP } from '../constant';
function createMethodDecorator(method: string) {
return function httpMethodDecorator(path: string) {
return function (proto: any, name: string) {
const target = proto.constructor;
const routeMap = Reflect.getMetadata(ROUTER_MAP, target, 'method') || [];
routeMap.push({ name, method, path });
Reflect.defineMetadata(ROUTER_MAP, routeMap, target, 'method');
};
};
}
export const post = createMethodDecorator('post');
export const get = createMethodDecorator('get');
export const del = createMethodDecorator('del');
export const put = createMethodDecorator('put');
export const patch = createMethodDecorator('patch');
export const options = createMethodDecorator('options');
export const head = createMethodDecorator('head');
export const all = createMethodDecorator('all');

装饰控制器的方法

export default class Sign {
@post('/login')
async login(ctx: Context) {
const { email, password } = ctx.request.body;
const users = await userDao.getUser({ email });
// ...
return ctx.body = { code: 0, message: '登录成功', data };
}
@post('/register')
async register(ctx: Context) {
const { email, password } = ctx.request.body;
const salt = makeSalt();
// ...
return ctx.body = { code: 0, message: '注册成功!', data };
}
}

收集元数据和添加路由

import 'reflect-metadata';
import fs from 'fs';
import path from 'path';
import { ROUTER_MAP } from './constant';
import { RouteMeta } from './type';
import Router from 'koa-router';
const addRouter = (router: Router) => {
const ctrPath = path.join(__dirname, 'controller');
const modules: ObjectConstructor[] = [];
fs.readdirSync(ctrPath).forEach(name => {
if (/^[^.]+?\.(t|j)s$/.test(name)) {
modules.push(require(path.join(ctrPath, name)).default);
}
});
modules.forEach(m => {
const routerMap: RouteMeta[] = Reflect.getMetadata(ROUTER_MAP, m, 'method') || [];
if (routerMap.length) {
const ctr = new m();
routerMap.forEach(route => {
const { name, method, path } = route;
router[method](path, ctr[name]);
});
}
});
};
export default addRouter;

最后

通过上述优化,Koa 项目的脚手架改造工作基本完成。

转载地址:http://icduz.baihongyu.com/

你可能感兴趣的文章
Node.js安装与配置指南:轻松启航您的JavaScript服务器之旅
查看>>
Node.js安装及环境配置之Windows篇
查看>>
Node.js安装和入门 - 2行代码让你能够启动一个Server
查看>>
node.js安装方法
查看>>
Node.js官网无法正常访问时安装NodeJS的方法
查看>>
Node.js的交互式解释器(REPL)
查看>>
Node.js的循环与异步问题
查看>>
Node.js高级编程:用Javascript构建可伸缩应用(1)1.1 介绍和安装-安装Node
查看>>
nodejs + socket.io 同时使用http 和 https
查看>>
NodeJS @kubernetes/client-node连接到kubernetes集群的方法
查看>>
Nodejs express 获取url参数,post参数的三种方式
查看>>
nodejs http小爬虫
查看>>
nodejs libararies
查看>>
nodejs npm常用命令
查看>>
nodejs npm常用命令
查看>>
Nodejs process.nextTick() 使用详解
查看>>
nodejs 创建HTTP服务器详解
查看>>
nodejs 发起 GET 请求示例和 POST 请求示例
查看>>
NodeJS 导入导出模块的方法( 代码演示 )
查看>>
nodejs 开发websocket 笔记
查看>>