typescriptを使用してkoa開発フレームワークを改造する

7687 ワード

原文アドレス:typescriptを使用してkoa開発フレームワークの強いタイプを改造するTypeScript開発体験とメンテナンスプロジェクトではJavaScriptに比べて明らかな優位性があり、よく使われる足場の改造も必要である.
次にkoaフレームベースのnodeバックエンド足場の改造を開始します.
  • プロジェクト開発環境とtypescriptコンパイル環境の構築;
  • node、koa、koaミドルウェア、および使用されるライブラリにタイプ化サポートを追加します.
  • typesriptの特性改造プロジェクトに基づく.

  • プロジェクト開発環境構築
    gulpに基づいて開発コンパイル環境を構築し、gulp-typescriptプラグインはtypescriptファイルをコンパイルするために使用され、gulp-nodemonはファイル内容の変更を監視し、自動的にnodeサービスをコンパイルし、再起動し、開発効率を高めることができる.
    npm install -D gulp gulp-nodemon gulp-typescript ts-node typescript
    

    gulpの構成
    gulpfile.jsの設定
    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);
    }
    
    //    js   dist  
    function toJs() {
      return src('src/**/*.ts')
        .pipe(tsProject())
        .pipe(dest('dist'));
    }
    
    // nodemon    ts   
    function runNodemon() {
      nodemon({
        inspect: true,
        script: 'src/app.ts',
        watch: ['src'],
        ext: 'ts',
        env: { NODE_ENV: 'development' },
        // tasks: ['build'],
      }).on('crash', () => {
        console.error('Application has crashed!
    '); }); } const build = series(clean, toJs); task('build', build); exports.build = build; exports.default = runNodemon;

    typescriptの構成
    tsconfig.jsonの設定
    {
      "compilerOptions": {
        "baseUrl": ".", // import       
        "outDir": "./dist", //       
        "module": "commonjs",
        "target": "esnext",// node      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の構成
    もちろんeslintもtypescript対サポートを追加します
    npm install -D @typescript-eslint/eslint-plugin @typescript-eslint/parser
    

    .eslintrc.jsonの設定
    {
      "env": {
        "es6": true,
        "node": true
      },
      "extends": [
        "eslint:recommended",
        "plugin:@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運転構成
    最後にpackageを設定します.jsonのscripts
      "scripts": {
        "start": "gulp",// dev
        "build": "gulp build", // output
        "eslint": "eslint --fix --ext .js,.ts src/",
        "server": "export NODE_ENV=production && node dist/app" // production server
      },
    

    タイプ化サポートの追加
    プロジェクトは主に以下のコンポーネントを使用しています.
  • jsonwebtoken
  • koa
  • koa-body
  • koa-compress
  • koa-favicon
  • koa-logger
  • koa-router
  • koa-static
  • koa2-cors
  • log4js

  • では、対応するtypeファイルをインストールします.もちろん@types/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アクセサリーを使用してプロジェクトを改造する
    .Netmvcフレームワークは、コントローラを装飾器で配置するのが便利で、typescriptの装飾器でも同様の機能を実現できます.ここでは反射に関するライブラリreflect-metadataを使用する必要があります.JavaやC#を使ったことのあるパートナーは、反射の原理に慣れていないに違いありません.
    httpリクエストの装飾を定義する
    ルーティング構成とコントローラメソッドの間で検索してマッチングする必要はありません
    import 'reflect-metadata'
    import { ROUTER_MAP } from '../constant'
    
    /**
     * @desc    http method    
     * @param {string} method - http method,  get、post、head
     * @return Decorator -    
     */
    function createMethodDecorator(method: string) {
      //         path     
      return function httpMethodDecorator(path: string) {
        return (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');
        };
      };
    }
    
    //    http 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
        }
      }
      
    }
    

    メタデータの収集とルーティングの追加
    対応するコントローラのメソッドにアクセサリーを追加しましたが、メタデータをどのように収集しますか?これはnodeが提供するfsファイルモジュールを使用する必要があります.nodeサービスが初めて起動したとき、controllerフォルダをスキャンして、すべてのコントローラモジュールに収集し、装飾器が収集したmetadataと組み合わせて、対応する方法をkoa-routerに追加することができます.
    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[] = [];
      //   controller   ,    controller
      fs.readdirSync(ctrPath).forEach(name => {
        if (/^[^.]+?\.(t|j)s$/.test(name)) {
          modules.push(require(path.join(ctrPath, name)).default)
        }
      });
      //   meta      
      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プロジェクトの足場の改造は基本的に完成して、ソースコードはkoa-serverを見てください