跳到主要内容

· 阅读需 3 分钟
Harry Chen

升级请参考 如何更新 Midway 中描述,请不要单独升级某个组件包。

很高兴给大家介绍我们的 3.11 新版本。

安全性更新

Upload 组件增加了安全性性能,在 file 上传模式下,我们发现在某些情况下文件的后缀和实际内容不匹配,导致可能会在服务器被动执行的安全性漏洞。

新版本我们增加了一个 MIME 配置,可以在上传时检查扩展名之外,额外检查 MIME 的类型,会更加安全。

export default {
// ...
upload: {
// ...
// 仅允许下面这些文件类型可以上传
mimeTypeWhiteList: {
'.jpg': 'image/jpeg',
}
},
}

更多细节可以查看我们的 Upload 组件

New Feature

精细化的 Mock 能力

基于框架新提供的 @Mock 装饰器,可以方便的在不同的阶段进行数据模拟。同时作为逻辑的一部分,这个功能可以在开发和测试期被自动执行,方便用户的开发期模拟数据。

文档请参考 数据模拟

中间件的 Match/Ignore

Middleware 的功能进一步增强,match 和 ignore 现在可以是 stringregexpfunction 或者他们的数组组合形式。

本地定时任务组件

之前我们提供了 bull 组件,用于分布式定时任务,在某些场景下,我们依旧需要单机的定时任务来赋值完成一些事项,原有的 task 组件实现了 cron 的部分,我们将其分离为 cron 组件,继续提供能力支持。

文档请参考 cron 组件

标签组件

一种抽象化的服务端能力,用于数据筛选和处理。

文档请参考 标签组件

· 阅读需 4 分钟
Harry Chen

新年快乐。

升级请参考 如何更新 Midway 中描述,请不要单独升级某个组件包。

这个版本更新了许多东西,请耐心看完。

Breaking

首先是 Breaking 的部分,这部分并非是框架本身的 API 变更,而是依赖或者行为可能会影响少部分用户,需要注意的部分。

  • 1、 @midwayjs/consul 依赖的 consul 模块从 0.x 升级到 v1 正式版,API 可能有更新(consul.acl 变更为 consul.acl.legacy),具体请查看 文档
  • 2、@midwayjs/jwt 依赖的jsonwebtoken 模块由于安全性问题,从 v8 升级到 v9,API 可能有更新,更多情况请查看 文档
  • 3、由于新增的 @Pipe 功能,@midwayjs/validate 新版本无需使用 @Validate 装饰器即可校验,可能会影响一部分之前未编写装饰器但是新版本却被验证的场景,具体请看下面关于 @Pipe 的介绍或者相关的文档。

New Feature

Pipe

新版本新增了一项 Pipe 能力,可以使参数装饰器的能力更进一步。

藉由此能力,新版本的 Validate 组件不再需要 @Validate 装饰器,代码会更加简洁。

旧:

@Controller('/api/user')
export class HomeController {

@Post('/')
@Validate()
async updateUser(@Body() user: UserDTO ) {
// user.id
}
}

新:

@Controller('/api/user')
export class HomeController {

@Post('/')
async updateUser(@Body() user: UserDTO ) {
// user.id
}
}

针对非 DTO 类型的校验,现在也可以使用 Pipe 进行处理,如果是字符串,会自动转为数字,并进行校验。

@Controller('/api/user')
export class HomeController {

@Post('/update_age')
async updateAge(@Body('age', [ParseIntPipe]) age: number ) {
// ...
}
}

当然 Pipe 的功能不仅如此,更多功能请查看 完整文档

TypeORM Logger

当 typeorm 组件未配置 logger 属性时,新版本会自动创建一个 typeormLogger 用于存储执行的 sql。

默认配置为:

midwayLogger: {
clients: {
typeormLogger: {
lazyLoad: true,
fileLogName: 'midway-typeorm.log',
enableError: false,
level: 'info',
},
},
}

lazyLoad 为新增的属性,可以使 logger 在一开始仅保留配置,等实际 getLogger 时才做初始化。

@Singleton 装饰器

简化原有的写法:

旧:

@Scope(ScopeEnum.Singleton)
@Provide()
class SingletonService {}

新:

@Singleton()
class SingletonService {}

app.getNamespace API

通过 app 上新增的 getNamespace API ,可以获取到当前的 app 归属框架的类型。

比如:

import { Application } from '@midwayjs/web';

@Controller()
class HomeController {

@App()
app: Application;

async invoke() {
// this.app.getNamespace() => 'egg'
}
}

其他的一些变化

  • 1、调整@midwayjs/core 默认 logger level 为 info,的 coreLogger 在服务器环境继续保留 warn
  • 2、faas 模块新增一些自定义触发器类型
  • 3、在 jest 测试环境下,初始化的报错之前会被 jest 吞掉,新版本会通过 console.error 进行输出
  • 4、修复 configuration 的 stop 生命周期,将以 imports 顺序的逆序执行
  • 5、修复 bootstrap 使用 sticky 模式时,文件上传时的错误
  • 6、支持 swager 的属性多类型展示
  • 7、在 midway-bin dev 下,应用在本地开发时也可以快速使用 --ssl 来启动 https 服务

· 阅读需 4 分钟
Harry Chen

大促积攒了约两周的需求,统一在 v3.9.0 发布。

升级请参考 如何更新 Midway 中描述,请不要单独升级某个组件包。

Breaking

从 v3.9.0 开始,Midway 仅支持 Node.js >=12.11.0 版本。

Features

1、bootstrap 新增进程模型

从 v3.9.0 开始,为了应对 socket.io 在 pm2 场景下的粘性会话,我们新增一种 master-worker 模型支持。简单来说,将由 pm2 来启动 midway 的 master,在 master 启动 worker,这样可以相对自由的定制 master 中的逻辑。

原有的 Bootstrap 之外,新增了一个 ClusterManager 来处理进程,示例如下:

const { ClusterManager, Bootstrap } = require('@midwayjs/bootstrap');

const clusterManager = new ClusterManager({
// 执行的子进程文件
exec: __filename,
// 进程数
count: 2,
});

if (clusterManager.isPrimary()) {
// 启动主进程
clusterManager.start();
} else {
// 原有子进程执行
Bootstrap.run();
}

关于 socket.io 的粘性会话,我们将在 socket.io 组件中介绍更多。

2、增加 @InjectClient 支持

为 ServiceFactory 类型添加一个 @InjectClient 装饰器,方便在多客户端的的时候选择注入。

比如使用多个 redis 组件的时候。

原来:

import { RedisServiceFactory } from '@midwayjs/redis';
import { join } from 'path';

@Provide()
export class UserService {

@Inject()
redisServiceFactory: RedisServiceFactory;

async save() {
const redis1 = this.redisServiceFactory.get('instance1');
const redis2 = this.redisServiceFactory.get('instance2');

//...

}
}

现在可以通过注入来简化。

import { RedisServiceFactory } from '@midwayjs/redis';
import { InjectClient } from '@midwayjs/core';

@Provide()
export class UserService {

@InjectClient(RedisServiceFactory, 'instance1')
redis1: RedisService;

@InjectClient(RedisServiceFactory, 'instance2')
redis2: RedisService;

async save() {
// this.redis1.set(...)
// this.redis2.set(...)
}
}

注意,所有继承于 ServiceFactory 的多实例组件都可以使用上述方法。

3、casbin 支持 watcher 抽象

除了社区的 casbin-redis-watcher,我们也提供了复用 redis 连接的 watcher,为了减少包,后续所有的 casbin/redis 相关的功能都将复用 casbin-redis-adapter 包。

使用示例:

import { MidwayAppInfo } from '@midwayjs/core';
import { join } from 'path';
import { createAdapter, createWatcher } from '@midwayjs/casbin-redis-adapter';

export default (appInfo: MidwayAppInfo) => {
return {
keys: '123456',
redis: {
clients: {
'node-casbin-official': {
host: '127.0.0.1',
port: 6379,
password: '',
db: '0',
},
'node-casbin-sub': {
host: '127.0.0.1',
port: 6379,
password: '',
db: '0',
}
}
},
casbin: {
// ...
policyAdapter: createAdapter({
clientName: 'node-casbin-official'
}),
policyWatcher: createWatcher({
pubClientName: 'node-casbin-official',
subClientName: 'node-casbin-sub',
})
},
};
}

由于 pub/sub 连接需要不同,这里定义了两个客户端,和 adapter 存储复用其中一个连接。

4、DataSource 的不同路径支持

为了解决不同用户的使用习惯,我们支持了大多数可能的通配形式,现在你可以在 DataSource 中使用很多以前的格式。

比如:

export default {
mysql: {
dataSource: {
dataSource1: {
// ...
entities: [
'entity', // 特定目录
'**/abc/**', // 仅获取包含 abc 字符的目录下的文件
'abc/**/*.ts', // 特定目录 + 通配
'abc/*.entity.ts', // 匹配后缀
'**/*.entity.ts', // 通配加后缀匹配
'**/*.{j,t}s', // 后缀匹配
]
},
// ...
// ...
}
}
}

· 阅读需 3 分钟
Harry Chen

v3.8.0 是在经过大促之后的第一个 minor 版本,积攒了很多新的能力。

升级请参考 如何更新 Midway 中描述,请不要单独升级某个组件包。

Features

1、etcd 组件

新增了一个 etcd 组件,方便用户使用,文档稍后提供。

import { ETCDService } from '@midwayjs/etcd';

@Provide()
export class UserService {

@Inject()
etcdService: ETCDService;

async invoke() {

const fooValue = await this.etcdService.get('foo').string();
console.log('foo was:', fooValue);
// ...
}
}

更多细节请查看 文档

2、ServiceFactory 支持设置默认客户端

ServiceFactory 提供了标准的多客户端能力,在默认的客户端中,我们可以设置非 default 的客户端作为默认客户端来使用。

这项能力支持 ServiceFactory 扩展出来的所有组件,包括 axios/cos/oss/redis/tablestore 等,用户自定义的组件也可以通过简单的适配享受到该能力。

比如,我们定义了多个 redis 客户端。

export default {
// ...
redis: {
clients: {
default: {
// ...
},
default2: {
// ...
},
},
},
}

默认注入的 RedisService 永远为 default 指向的客户端,而新版本我们可以通过设置默认的客户端名,来选择默认的客户端。

比如:

export default {
// ...
redis: {
clients: {
default: {
// ...
},
default2: {
// ...
},
},
defaultClientName: 'default2'
},
}

那么实际获取的 redisService 中是 default2 这个实例。


@Provide()
export class UserService {

@Inject()
redisService: RedisService;

async invoke() {
// this.redisService 中包裹的是 default2
}
}

3、数据源类型增加 @InjectDataSource 装饰器

为了简化获取数据源的过程,我们提供了一个新的 @InjectDataSource 装饰器,支持 mikro/sequelize/typeorm。

比如:

import { InjectDataSource } from '@midwayjs/typeorm';
import { DataSource, Repository } from 'typeorm';

@Provide()
export class UserService {

@InjectDataSource()
defaultDataSource: DataSource;

async invoke() {

// ...
}
}

也可以指定数据源。

import { InjectDataSource } from '@midwayjs/typeorm';
import { DataSource, Repository } from 'typeorm';

@Provide()
export class UserService {

@InjectDataSource('default')
defaultDataSource: DataSource;

async invoke() {
// ...
}
}

Bugfix

  • 1、修复 windows 下 entity 通配扫描,之前 windows 下的 entity 如果使用了通配符,会扫描失败,导致 entity 无法正确的加入到数据源中,新版本修复了该问题。
  • 2、bull 的 Queue 定义处理问题,现在文档已经做了修改,注入的类型可以由 IQueue 变为 BullQueue

Performance

移除了 babel 编译出的 class 的兼容判断,框架整体性能提升约一倍。

· 阅读需 2 分钟
Harry Chen

由于最近 node v18 标记为 LTS,社区相关的相关的依赖都移除了 node v12 的支持,导致 Midway 的基建,单测已经无法正常的执行。

虽然 Midway 框架本身支持在 Node v12 下运行,但是例如 jest 等工具的最新版本已经无法执行。经过内部讨论后决定,在 Github Action 中移除 Midway 以及相关库的 Node v12 的单测,为此,相关的依赖会进行调整,包括:

  • 1、脚手架的变更
    • @midwayjs/cli 升级为 ^2.0.0
    • jest@types/jestts-jest 升级为 v29 版本
    • typescript 升级为 4.8.x
  • 2、Midway 本身
    • 移除 node v12 的 github action 执行
    • 鉴于部分环境的情况,继续经验支持 node v12 的运行,有 node v12 的问题可以 issue 提问

依赖的变更可以参考:

"devDependencies": {
"@midwayjs/cli": "^2.0.0",
"@types/jest": "^29.2.0",
"jest": "^29.2.2",
"ts-jest": "^29.0.3",
"typescript": "~4.8.0"
}