从 Serverless v1 迁移到 v2
本文章介绍如何从 Serverless v1.0 迁移到 Serverless v2.0。
Midway Serverless 2.0 的升级主要体现在架构和包的变化上,功能本身变化不大。
升级方式
1、全局 CLI 的升级
移除原有的 @midwayjs/faas-cli
包,不再使用 f
全局命令,改为项目下的包和命令。
$ npm uninstall @midwayjs/faas-cli -g
2、项目包版本的升级
依赖包升级。
"dependencies": {
"@midwayjs/faas": "^2.0.0"
},
开发依赖包升级(向传统应用靠拢)。
"devDependencies": {
"@midwayjs/cli": "^1.2.45",
"@midwayjs/mock": "^2.8.7",
"@midwayjs/serverless-app": "^2.8.7",
"@midwayjs/fcli-plugin-fc": "^1.2.45",
"@types/jest": "^26.0.10",
"@types/node": "^14",
"typescript": "^4.0.0"
}
- 1、将原有的 mocha 测试换成了 jest,所以
@types/mocha
变为了@types/jest
。 - 2、
@midwayjs/serverless-invoke
被移除,由于采用了应用的测试方式,不再需要。 - 3、平台模块区分,
@midwayjs/fcli-plugin-fc
该模块是用于阿里云 FC 环境的工具包,如果要发布到腾讯云 SCF 环境,请使用midwayjs/fcli-plugin-scf
。
3、脚本的升级
向应用靠拢,提供了 dev
、 test
、 deploy
命令。
"scripts": {
"dev": "midway-bin dev --ts",
"test": "midway-bin test --ts",
"deploy": "midway-bin deploy"
},
- 原有的
build
命令被移除,因为部署时 deploy 会自动 build - 原有的
f test
命令将和开发应用相同,替换为midway-bin test --ts
- 原有的
f dev
和 debug,将和开发应用相同,统一使用midway-bin dev --ts
,调试方式也相同
4、包定义变更
常见定义变更。
原有的 IFaaSApplication
变为 Application
,和应用一致从 @midwayjs/faas
包获取。
import { Application, Context } from '@midwayjs/faas';
原有的小写装饰器变为大写,和应用一致从 @midwayjs/decorator
获取。
import { App, Config } from '@midwayjs/decorator';
原有的 ILifeCycle
, IMidwayContainer
为容器定义,和应用一致从 @midwayjs/core
获取。
import { ILifeCycle, IMidwayContainer } from '@midwayjs/core';
5、运行
HTTP 类的函数,本地直接使用 npm run dev
运行,非 HTTP 类的函数,请使用 npm run test
进行测试开发。
可选的调整
1、@Func 装饰器升级为 @ServerlessTrigger 装饰器
现有代码依旧可以使用 @Func
装饰器兼容,新代码请使用 @ServerlessTrigger
装饰器,构建器可以通过分析 @ServerlessTrigger
装饰器,自动生成 yml 内容。
2、f.yml
使用了 @ServerlessTrigger
装饰器后,f.yml 中的 functions 字段可以移除。编译时会自动根据代码生成函数路由信息。
3、测试代码的调整
HTTP 类型的函数,使用和应用相同的封装了 supertest 的 createHttpRequest
方法创建 HTTP 客户端。
import { createFunctionApp, close, createHttpRequest } from '@midwayjs/mock';
import { Framework, Application } from '@midwayjs/serverless-app';
describe('test/hello_aliyun.test.ts', () => {
let app: Application;
beforeAll(async () => {
// create app
app = await createFunctionApp<Framework>();
});
afterAll(async () => {
await close(app);
});
it('should get result from api gateway trigger', async () => {
const result = await createHttpRequest(app).get('/').query({
name: 'zhangting',
});
expect(result.text).toEqual('hello zhangting');
});
});
除了类 HTTP 触发器之外,我们还有其他比如定时器、对象存储等函数触发器,这些触发器由于和网关关系密切,不能使用 HTTP 行为来测试,而是使用传统的方法调用来做。
import { createFunctionApp, close, createHttpRequest } from '@midwayjs/mock';
import { Framework, Application } from '@midwayjs/serverless-app';
import { createInitializeContext } from '@midwayjs/serverless-fc-trigger';
describe('test/hello_aliyun.test.ts', () => {
let app: Application;
let instance: HelloAliyunService;
beforeAll(async () => {
// 创建函数 app
app = await createFunctionApp<Framework>(join(__dirname, '../'), {
initContext: createInitializeContext(), // 这里传入了 aliyun 特有的初始化上下文数据
});
// 拿到服务类
instance = await app.getServerlessInstance<HelloAliyunService>(HelloAliyunService);
});
afterAll(async () => {
await close(app);
});
it('should get result from event trigger', async () => {
// 调用函数方法,传入参数
expect(await instance.handleEvent('hello world')).toEqual('hello world');
});
});