<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          手把手帶你學習Midwayjs實戰(zhàn)

          共 13929字,需瀏覽 28分鐘

           ·

          2022-05-28 18:57

          前言

          哈嘍,大家好,我是migor,一個樂于分享工作中所用的一些知識的人,目前專注于前端和Node.js技術棧的分享,工作中目前負責提效平臺的搭建和開發(fā)。

          經(jīng)常有人問,現(xiàn)在都2022年了,還要學習Node.js么?我想這個問題,可能每個前端開發(fā)者,都會在工作到一定階段思考這個問題??梢院苊鞔_的告訴大家,學習Node.js 可能是將來每個前端開發(fā)者必備的一項技能。

          Angular 發(fā)布的同一年(2009年),Node.js 也隨之登臺,Node.js 的出現(xiàn)帶來的第一個好處就是前端工程化的成熟,前端構建工具開始百花齊放。這時的前端已經(jīng)不再是一個簡單編寫幾行 JavaScript 即可完成的事情,前端開發(fā)開始出現(xiàn)了前端工程師這個職位,專職前端研發(fā)人員開始在各個公司中普及,前后端協(xié)作問題也開始加劇。

          BFF

          隨著 Node.js 的成熟,在2015年,基于BFF(Backgroud For Frontend, 服務于前端的后端)的架構理念被提出,BFF 架構通過在UI 和服務端之間加入中間層,解決了前后端職責難以劃分的問題。

          如圖所示,由于前端的邏輯復雜性不斷增加,增加了專門用于處理用戶界面邏輯的服務層,同時后端邏輯也完成下沉,基于微服務架構的后端服務逐漸成型,通過基于Node.jsBFF 層,前后端形成了比較清晰的分工,也就是進入了前端工程師時代。

          Node.js的基本原理

          先看一下早期的Node.js 結構圖,來自Node.js 之父 Ryan Dahl的演講稿,它簡要的介紹了Node.js 是基于Chrome V8引擎構建的,由于事件循環(huán)Event Loop 分發(fā)I/O 任務, 最終工作線程Work Thread 將任務丟到線程池Thread Pool 里去執(zhí)行, 而事件循環(huán)只要等待執(zhí)行結果就可以了


          核心

          • Chrome V8 解釋并執(zhí)行 JavaScript 代碼(這就是為什么瀏覽器能執(zhí)行 JavaScript 原因)
          • libuv 由事件循環(huán)和線程池組成,負責所有 I/O 任務的分發(fā)與執(zhí)行

          常用的框架

          框架名稱特性
          Express簡單、實用、路由中間件等俱全
          Nest.js支持ts,易于拓展,結合了函數(shù)式編程等
          Koa.js體積更小,代表現(xiàn)代和未來
          egg.js基于Koa,在開發(fā)上有更大便利
          Midway支持ts, 漸進式的Node框架,更接近與nest

          為什么選擇Midway

          • 如果說這兩年那個語言在前端最火,我想TypeScript 肯定有一席之地,強約束性的語言使得在構建Node.js應用時,提供了類型檢查等約束能力,使得Node.js 更安全等。Midway 基于TypeScript開發(fā),對于TypeScript的支持更好一些。

          • 最近在深耕于公司的基礎建設,使用的Node.js 框架剛好是Midwayjs。

          • Midwayjs 提供了Web中間件的能力。

          Midway簡介

          Midway 是阿里巴巴 - 淘寶前端架構團隊,基于漸進式理念研發(fā)的 Node.js 框架。

          Midway 基于 TypeScript 開發(fā),結合了面向對象(OOP + Class + IoC)函數(shù)式(FP + Function + Hooks)兩種編程范式,并在此之上支持了 Web / 全棧 / 微服務 / RPC / Socket / Serverless 等多種場景,致力于為用戶提供簡單、易用、可靠的 Node.js 服務端研發(fā)體驗。

          多編程范式

          Midway 支持面向對象與函數(shù)式兩種編程范式,你可以根據(jù)實際研發(fā)的需要,選擇不同的編程范式來開發(fā)應用。

          面向對象(OOP + Class + IoC)

          Midway 支持面向對象的編程范式,為應用提供更優(yōu)雅的架構。

          下面是基于面向對象,開發(fā)路由的示例。

          //?src/controller/home.ts
          import?{?Controller,?Get?}?from?'@midwayjs/decorator';
          import?{?Context?}?from?'@midwayjs/koa';

          @Controller('/')
          export?class?HomeController?{

          ??@Inject()
          ??ctx:?Context

          ??@Get('/')
          ??async?home()?{
          ????return?{
          ??????message:?'Hello?Midwayjs!',
          ??????query:?this.ctx.ip
          ????}
          ??}
          }

          函數(shù)式(FP + Function + Hooks)

          Midway 也支持函數(shù)式的編程范式,為應用提供更高的研發(fā)效率。

          下面是基于函數(shù)式,開發(fā)路由接口的示例。

          //?src/api/index.ts

          import?{?useContext?}?from?'@midwayjs/hooks'
          import?{?Context?}?from?'@midwayjs/koa';

          export?default?async?function?home?()?{
          ??const?ctx?=?useContext()

          ??return?{
          ????message:?'Hello?Midwayjs!',
          ????query:?ctx.ip
          ??}
          }

          環(huán)境準備

          首先確保你已經(jīng)安裝了Node.js,Node.js 安裝會附帶npx 和一個npm包運行程序,Midway 3.0.0 最低版本要求12.x。如果需要幫助,請參考如何安裝Node.js環(huán)境[1]。

          項目創(chuàng)建

          使用npm init midway來創(chuàng)建項目

          npm?init?midway

          我們這里使用3.0版本,因此我們這里選擇koa-v3,輸入項目名稱, 腳手架會幫我們創(chuàng)建一個簡單的項目工程,等安裝完成。

          我們使用Vscode 打開項目??梢缘玫浆F(xiàn)在的工程目錄

          midway-demo
          ├──?README.md
          ├──?README.zh-CN.md
          ├──?bootstrap.js
          ├──?jest.config.js
          ├──?package.json
          ├──?src
          │???├──?config
          │???│???├──?config.default.ts
          │???│???└──?config.unittest.ts
          │???├──?configuration.ts
          │???├──?controller
          │???│???├──?api.controller.ts
          │???│???└──?home.controller.ts
          │???├──?filter
          │???│???├──?default.filter.ts
          │???│???└──?notfound.filter.ts
          │???├──?interface.ts
          │???├──?middleware
          │???│???└──?report.middleware.ts
          │???└──?service
          │???????└──?user.service.ts
          ├──?test
          │???└──?controller
          │???????├──?api.test.ts
          │???????└──?home.test.ts
          └──?tsconfig.json

          整個項目包括了一些最基本的文件和目錄

          • src 整個工程的源碼目錄,之后所有的開發(fā)代碼都將放在這個文件夾下面
          • test 測試目錄,之后所有的代碼測試文件都在這里
          • package.json Node.js 項目基礎的包管理配置文件,這個想必大家都很熟悉
          • tsconfig.json TypeScript 編譯配置文件.

          src目錄下面,常用的有:

          • config 業(yè)務的配置目錄
          • controller web controller 目錄
          • filter 過濾器目錄
          • interface.ts 業(yè)務的ts定義文件
          • middleware 中間件目錄
          • service 服務邏輯目錄

          啟動項目

          yarn?dev

          warning?../../../../../package.json:?No?license?field
          $?cross-env?NODE_ENV=local?midway-bin?dev?--ts
          [?Midway?]?Start?Server?at??http://127.0.0.1:7001

          在瀏覽器中輸入127.0.0.1:7001

          路由

          我們來看一下代碼中的controller 文件夾下面的home.controller.ts 文件

          import?{?Controller,?Get?}?from?'@midwayjs/decorator';

          @Controller('/')
          export?class?HomeController?{
          ??@Get('/')
          ??async?home():?Promise<string>?{
          ????return?'Hello?Midwayjs!';
          ??}
          }

          我們找到了瀏覽器中的輸出Hello Midwayjs!

          路由裝飾器

          @controller 裝飾器標注了控制器,裝飾器有一個可選參數(shù),用于進行路由前綴,這樣控制器下面的所有路由都會帶上這個前綴。

          我們修改一下裝飾器中的內容

          import?{?Controller,?Get?}?from?'@midwayjs/decorator';

          @Controller('/test')
          export?class?HomeController?{
          ??@Get('/')
          ??async?home():?Promise<string>?{
          ????return?'Hello?Midwayjs!';
          ??}
          }

          在瀏覽器中輸入127.0.0.1:7001 報錯

          報錯信息告訴我們路由找不到,那么我們改一下瀏覽器中的路由127.0.0.1:7001/test,我們得到了我們想要的結果,這里我們可以知道裝飾器中的參數(shù)匹配我們的路由

          Http裝飾器

          常見的 Http裝飾器, ?@Get@Post 、 @Put() 、 @Del() 、 @Patch() 、 @Options() 、 @Head()@All() ,表示各自的 HTTP 請求方法。

          我們改寫一下代碼

          import?{?Controller,?Get,?Post?}?from?'@midwayjs/decorator';

          @Controller('/test')
          export?class?HomeController?{
          ??@Post('/')
          ??async?home():?Promise<string>?{
          ????return?'Hello?Midwayjs!';
          ??}
          }

          通過使用Postman 調用接口,將請求方式改為post,可以看到我們拿到我們請求的接口了。

          全局路由前綴

          在工程項目中,我們常常使用一些路由前綴去區(qū)分不同服務之間的作用,那么相同的路由前綴,在每個controller里面加入,顯然很麻煩,如果要改變前綴名稱,在后期工程相對較大,接口較多的時候,豈不是要一個個去改,在這里我們配置全局的路由前綴。

          我們修改config/config.default.ts 文件,代碼修改如下

          import?{?MidwayConfig?}?from?'@midwayjs/core';

          export?default?{
          ??//?use?for?cookie?sign?key,?should?change?to?your?own?and?keep?security
          ??keys:?'1653223786698_4903',
          ??koa:?{
          ????port:?7001,
          ????globalPrefix:?'/demo',
          ??},
          }?as?MidwayConfig;

          保存文件之后,服務不需要我們手動重啟,我們請求一下http://127.0.0.1/demo/test,服務返回了我們的內容。

          依賴注入

          依賴注入(DI)、控制反轉(IoC)等是Spring的核心思想,那么在midwayjs中通過裝飾器的輕量特性,讓依賴注入變得非常優(yōu)雅.

          舉個例子??:

          .
          ├──?package.json
          ├──?src
          │???├──?controller??????????????????????????????????????????#?控制器目錄
          │???│???└──?api.controller.ts
          │???└──?service?????????????????????????????????????????????#?服務目錄
          │???????└──?user.service.ts
          └──?tsconfig.json

          我們實現(xiàn)一下文件的代碼

          //?api.controller.ts

          import?{?Inject,?Controller,?Get,?Query?}?from?'@midwayjs/decorator';
          import?{?Context?}?from?'@midwayjs/koa';
          import?{?UserService?}?from?'../service/user.service';

          @Controller('/api')
          export?class?APIController?{
          ??@Inject()
          ??ctx:?Context;

          ??@Inject()
          ??userService:?UserService;

          ??@Get('/get_user')
          ??async?getUser(@Query('uid')?uid)?{
          ????const?user?=?await?this.userService.getUser({?uid?});
          ????return?{?success:?true,?message:?'OK',?data:?user?};
          ??}
          }
          //?user.service.ts

          import?{?Provide?}?from?'@midwayjs/decorator';
          import?{?IUserOptions?}?from?'../interface';

          @Provide()
          export?class?UserService?{
          ??async?getUser(options:?IUserOptions)?{
          ????return?{
          ??????uid:?options.uid,
          ??????username:?'mockedName',
          ??????phone:?'12345678901',
          ??????email:?'[email protected]',
          ????};
          ??}
          }

          @Provide 的作用是告訴 依賴注入容器 ,我需要被容器所加載。@Inject 裝飾器告訴容器,我需要將某個實例注入到屬性上。

          上面例子??上,我們實現(xiàn)了一個UserService并通過@Provide注入到容器中,在app.controller中,我們通過@Inject 拿到了userService的實例。

          那么我們請求一下接口:

          調試

          我們在擴展里面搜索JavaScript Debugger

          點擊下拉箭頭,選擇JavaScript Debug Terminal, .

          輸入命令yarn dev,在需要debugger的位置打上斷點

          Postman 中請求接口,可以看到代碼執(zhí)行到斷點位置

          連接Mysql

          前面我們已經(jīng)實現(xiàn)了接口的請求,那么作為后端項目,必然會涉及到數(shù)據(jù)的CURD,這里必須得使用數(shù)據(jù)庫實現(xiàn)數(shù)據(jù)的持久化了,數(shù)據(jù)庫我們這篇文章使用的是Mysql, 如果是使用的Mongoose可以參考筆者的另一篇文章MidwayJs多數(shù)據(jù)庫配置,并實現(xiàn)Mongoose自增Id。

          數(shù)據(jù)庫安裝

          筆者使用的是Homebrew來安裝的Mysql,如果沒有安裝Homebrew,可以直接下載安裝包安裝,或者先安裝Homebrew,詳細步驟參見Homebrew[2] 官網(wǎng)。

          //?確認brew在正常工作
          brew?doctor

          //?更新包
          brew?update

          //?或者更新全局所有包
          brew?upgrade

          //?安裝mysql
          brew?install?mysql

          數(shù)據(jù)庫服務啟動

          安裝完成之后啟動Mysql服務

          mysql.server?start

          啟動完成。

          Mysql可視化

          我們使用可視化工具來管理數(shù)據(jù)庫,這里筆者使用的是 Navicat Premium,可視化工具相對比較多,你可以使用自己喜歡的可視化工具管理數(shù)據(jù)庫。

          我們創(chuàng)建一個Mysql數(shù)據(jù)庫連接,連接名稱可以隨意取自己喜歡的,輸入默認的端口,輸入自己數(shù)據(jù)庫的密碼。

          連接成功之后,我們創(chuàng)建一個Midway的數(shù)據(jù)表

          創(chuàng)建成功之后

          引入TypeORM

          TypeORM[3]node.js 現(xiàn)有社區(qū)最成熟的對象關系映射器(ORM )。Midway 和 TypeORM 搭配,使開發(fā)更簡單。

          安裝組件

          安裝ORM組件,提供數(shù)據(jù)庫ORM 能力

          yarn?add?@midwayjs/orm?typeorm?--save

          引入組件

          src/configuration.ts引入ORM組件,代碼如下:

          //?configuration.ts
          import?{?Configuration?}?from?'@midwayjs/decorator';
          import?*?as?orm?from?'@midwayjs/orm';
          import?{?join?}?from?'path';

          @Configuration({
          ??imports:?[
          ????//?...
          ????orm?????????????????????????????????????????????????????????//?加載?orm?組件
          ??],
          ??importConfigs:?[
          ????join(__dirname,?'./config')
          ??]
          })
          export?class?ContainerConfiguratin?{

          }

          安裝數(shù)據(jù)庫Driver

          yarn?add?mysql?mysql2?--save

          配置數(shù)據(jù)庫連接

          src/config/config.default.ts 中配置mysql 連接。

          import?{?MidwayConfig?}?from?'@midwayjs/core';

          export?default?{
          ??//?use?for?cookie?sign?key,?should?change?to?your?own?and?keep?security
          ??keys:?'1653223786698_4903',
          ??koa:?{
          ????port:?7001,
          ????globalPrefix:?'/demo',
          ??},
          ??orm:?{
          ????type:?'mysql',
          ????host:?'127.0.0.1',
          ????port:?3306,
          ????username:?'root',
          ????password:?'',?//?數(shù)據(jù)庫密碼
          ????database:?'midway',?//?數(shù)據(jù)表
          ????synchronize:?true,
          ????logging:?false,
          ??},
          }?as?MidwayConfig;

          保存之后重啟,數(shù)據(jù)庫連接成功

          實現(xiàn)model

          src文件夾下面創(chuàng)建model文件夾,創(chuàng)建一個數(shù)據(jù)庫表

          聲明一個實體table

          //?user.ts

          import?{?EntityModel?}?from?'@midwayjs/orm';
          import?{?Column,?PrimaryGeneratedColumn?}?from?'typeorm';

          //?映射user?table
          @EntityModel({?name:?'user'?})
          export?class?UserModel?{
          ??//?聲明主鍵
          ??@PrimaryGeneratedColumn('increment')?id:?number;
          ?
          ??//?映射userName和user表中的user_name對應
          ??@Column({?name:?'user_name'?})?userName:?string;

          ??@Column({?name:?'age'?})?age:?number;

          ??@Column({?name:?'description'?})?description:?string;
          }

          修改src/user.service.ts文件

          import?{?Provide?}?from?'@midwayjs/decorator';
          import?{?InjectEntityModel?}?from?'@midwayjs/orm';
          import?{?Repository?}?from?'typeorm';
          import?{?IUserOptions?}?from?'../interface';
          import?{?UserModel?}?from?'../model/user';

          @Provide()
          export?class?UserService?{
          ??@InjectEntityModel(UserModel)?userModel:?Repository;

          ??async?getUser(options:?IUserOptions)?{
          ????return?{
          ??????uid:?options.uid,
          ??????username:?'mockedName',
          ??????phone:?'12345678901',
          ??????email:?'[email protected]',
          ????};
          ??}
          ??
          ??async?addUser()?{
          ????let?record?=?new?UserModel();

          ????record?=?this.userModel.merge(record,?{
          ??????userName:?'migor',
          ??????age:?18,
          ??????description:?'test',
          ????});

          ????try?{
          ??????const?created?=?await?this.userModel.save(record);

          ??????return?created;
          ????}?catch?(e)?{
          ??????console.log(e);
          ????}
          ??}
          }

          通過InjectEntityModel 裝飾器,注入實例化userModel,啟動服務之后,我們在midway數(shù)據(jù)表中增加user table

          修改src/controller/api.controller.ts

          import?{?Inject,?Controller,?Get,?Query?}?from?'@midwayjs/decorator';
          import?{?Context?}?from?'@midwayjs/koa';
          import?{?UserService?}?from?'../service/user.service';

          @Controller('/api')
          export?class?APIController?{
          ??@Inject()
          ??ctx:?Context;

          ??@Inject()
          ??userService:?UserService;

          ??@Get('/get_user')
          ??async?getUser(@Query('uid')?uid)?{
          ????const?user?=?await?this.userService.getUser({?uid?});
          ????return?{?success:?true,?message:?'OK',?data:?user?};
          ??}

          ??@Get('/add_user')
          ??async?addUser()?{
          ????const?user?=?await?this.userService.addUser();
          ????return?{?success:?true,?message:?'OK',?data:?user?};
          ??}
          }

          Postman中調用add_user接口

          我們可以看到已經(jīng)能正常返回我們保存的值了,那么我們去數(shù)據(jù)庫看一下,數(shù)據(jù)是否保存了,刷新一下數(shù)據(jù)庫,我們可以看到數(shù)據(jù)已經(jīng)保存成功。

          大功告成,至此我們完成數(shù)據(jù)的保存,那么后面我們可以進行數(shù)據(jù)的查詢,刪除,更新等。代碼如下

          user.service.ts中添加如下代碼

          // 刪除用戶
          async deleteUser() {
          const record = await this.userModel
          .createQueryBuilder()
          .delete()
          .where({ userName: 'migor' })
          .execute();

          const { affected } = record || {};

          return affected > 0;
          }

          // 更新用戶信息
          async updateUser() {
          try {
          const result = await this.userModel
          .createQueryBuilder()
          .update()
          .set({
          description: '測試更新',
          })
          .where({ userName: 'migor' })
          .execute();

          const { affected } = result || {};

          return affected > 0;
          } catch (e) {
          console.log('接口更新失敗');
          }
          }

          // 查詢
          async getUserList() {
          const users = await this.userModel
          .createQueryBuilder()
          .where({ userName: 'migor' })
          .getMany();

          return users;
          }

          api.controller.ts中增加相應的接口

          @Get('/get_user_list')
          async?getUsers()?{
          ??const?user?=?await?this.userService.getUserList();
          ??return?{?success:?true,?message:?'OK',?data:?user?};
          }

          @Get('/update_user')
          async?updateUser()?{
          ??const?user?=?await?this.userService.updateUser();
          ??return?{?success:?true,?message:?'OK',?data:?user?};
          }

          @Get('/delete_user')
          async?deleteUser()?{
          ??const?user?=?await?this.userService.deleteUser()
          ??return?{?success:?true,?message:?'OK',?data:?user?};
          }

          接入Swagger

          安裝組件

          接入swagger組件和swagger ui組件

          yarn?add?@midwayjs/swagger?swagger-ui-dist

          開啟組件

          configuration.ts 中增加組件

          import?{?Configuration,?App?}?from?'@midwayjs/decorator';
          import?*?as?koa?from?'@midwayjs/koa';
          import?*?as?validate?from?'@midwayjs/validate';
          import?*?as?info?from?'@midwayjs/info';
          import?{?join?}?from?'path';
          import?*?as?orm?from?'@midwayjs/orm';
          import?*?as?swagger?from?'@midwayjs/swagger';
          //?import?{?DefaultErrorFilter?}?from?'./filter/default.filter';
          //?import?{?NotFoundFilter?}?from?'./filter/notfound.filter';
          import?{?ReportMiddleware?}?from?'./middleware/report.middleware';

          @Configuration({
          ??imports:?[
          ????koa,
          ????validate,
          ????{
          ??????component:?info,
          ??????enabledEnvironment:?['local'],
          ????},
          ????orm,
          ????swagger,
          ??],
          ??importConfigs:?[join(__dirname,?'./config')],
          })
          export?class?ContainerLifeCycle?{
          ??@App()
          ??app:?koa.Application;

          ??async?onReady()?{
          ????//?add?middleware
          ????this.app.useMiddleware([ReportMiddleware]);
          ????//?add?filter
          ????//?this.app.useFilter([NotFoundFilter,?DefaultErrorFilter]);
          ??}
          }

          項目自動重啟成功之后,訪問地址

          • UI: http://127.0.0.1:7001/swagger-ui/index.html
          • JSON: http://127.0.0.1:7001/swagger-ui/index.json

          啟用之后可以查看到對應的接口

          swagger組件會自動識別各個@Controller中每個路由方法的@Body()@Query()、@Param() 裝飾器,提取路由方法參數(shù)和類型。

          增加接口標簽

          我們希望給接口增加標簽注釋,這樣才能更好的列舉接口的定義

          import?{?Inject,?Controller,?Get,?Query?}?from?'@midwayjs/decorator';
          import?{?Context?}?from?'@midwayjs/koa';
          import?{?ApiOperation?}?from?'@midwayjs/swagger';
          import?{?UserService?}?from?'../service/user.service';

          @Controller('/api')
          export?class?APIController?{
          ??@Inject()
          ??ctx:?Context;

          ??@Inject()
          ??userService:?UserService;

          ??@ApiOperation({?summary:?'獲取單個用戶'?})
          ??@Get('/get_user')
          ??async?getUser(@Query('uid')?uid)?{
          ????const?user?=?await?this.userService.getUser({?uid?});
          ????return?{?success:?true,?message:?'OK',?data:?user?};
          ??}

          ??@ApiOperation({?summary:?'增加單個用戶'?})
          ??@Get('/add_user')
          ??async?addUser()?{
          ????const?user?=?await?this.userService.addUser();
          ????return?{?success:?true,?message:?'OK',?data:?user?};
          ??}

          ??@ApiOperation({?summary:?'獲取用戶列表'?})
          ??@Get('/get_user_list')
          ??async?getUsers()?{
          ????const?user?=?await?this.userService.getUserList();
          ????return?{?success:?true,?message:?'OK',?data:?user?};
          ??}
          ??@ApiOperation({?summary:?'更新單個用戶'?})
          ??@Get('/update_user')
          ??async?updateUser()?{
          ????const?user?=?await?this.userService.updateUser();
          ????return?{?success:?true,?message:?'OK',?data:?user?};
          ??}
          ??@ApiOperation({?summary:?'刪除單個用戶'?})
          ??@Get('/delete_user')
          ??async?deleteUser()?{
          ????const?user?=?await?this.userService.deleteUser();
          ????return?{?success:?true,?message:?'OK',?data:?user?};
          ??}
          }

          重啟之后,可以查看swagger ui界面,標簽增加成功。

          總結

          至此我們已經(jīng)完成了Midwayjs基本功能的學習,包括搭建,數(shù)據(jù)庫的映射,簡單的CRUD,以及ORMSwagger的接入了。

          不知不覺搞到了12點,時間有點太晚了,關于接口傳參,數(shù)據(jù)校驗等問題,在后續(xù)的文章中會繼續(xù)寫,我們后面會進行一個博客前后端搭建的系列文章,后續(xù)帶你繼續(xù)學習midway。

          肝文不易,你的每個點贊和關注都是對我最大的鼓勵,比心??。

          ?
          參考資料
          ?
          [1]

          如何安裝Node.js環(huán)境: http://midwayjs.org/docs/how_to_install_nodejs

          [2]

          Homebrew: https://brew.sh/

          [3]

          TypeORM: https://github.com/typeorm/typeorm


          瀏覽 97
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  婷婷成人娱乐网 | 国产99九九久久无码精品 | 韩国一区二区三区在线观看 | 国内精品久久久久久久久久变脸 | 操大逼视频 |