- 后端
- 微服务
- 云原生
【免费下载链接】midway
🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈
本篇技术指南围绕 Midway 框架在阿里云函数计算(FC)上的完整落地路径展开:从三种部署类型(内置运行时、自定义运行时、自定义容器)的选型对比,到内置运行时下 Event、HTTP、API 网关、Timer、OSS、MNS 等触发器的编码与本地测试,再到基于 Serverless Devs 的s.yaml部署与deploy.sh自动化脚本,最后覆盖自定义运行时接入 9000 端口的改造方式。读完本文,你将掌握用 Midway 编写函数、在本地模拟平台事件做单元测试,以及将纯函数或标准 Web 应用发布到阿里云 FC 的完整实战方案。
部署类型概览
阿里云的函数计算(FC)提供多种部署形态,Midway 官方文档将其归纳为三种主要类型,分别对应在 FC 控制台创建函数时的三种方式,适用场景与交付媒介各不相同:
| 名称 | 能力限制 | 描述 | 部署媒介 |
|---|---|---|---|
| 内置运行时 | 不支持流式请求和响应;不支持太大的请求和响应入参 | 只能部署函数接口,不需要自定义端口,构建出 zip 包给平台部署 | zip 包部署 |
| 自定义运行时(Custom Runtime) | — | 可以部署标准应用,启动 9000 端口,使用平台提供的系统镜像,构建出 zip 包给平台部署 | zip 包部署 |
| 自定义容器(Custom Container) | — | 可以部署标准应用,启动 9000 端口,自己控制所有环境依赖,构建出 Dockerfile 提供给平台部署 | Dockerfile 部署 |
从部署形态上看:
- 内置运行时是最轻量的方式,Midway 把函数接口打包为 zip 交给平台,适合纯函数场景;
- 自定义运行时允许你跑完整的 Web 应用(Midway koa / Egg / Express 项目),但需监听平台约定的 9000 端口;
- 自定义容器进一步把依赖打包进 Docker 镜像,适合对系统环境有强控制需求的场景。
在仓库中,与阿里云 FC 强绑定的适配器是 packages-serverless/midway-fc-starter,其 README 明确指出该模块用于“包裹无法定制运行时的 FaaS 平台,比如阿里云 FC”,并导出了BootstrapStarter作为平台与 Midway 之间的桥接层。
纯函数开发(内置运行时)
内置运行时部署的核心是“纯函数”:不需要自定义端口,函数接口在平台注册后由触发器直接调用。下面以官方示例HelloAliyunService展开讲解各触发器的编码方式。
触发器代码
所有触发器都通过@ServerlessTrigger装饰器绑定,装饰器与类型定义来自@midwayjs/core与@midwayjs/faas。代码统一以@Provide()声明服务类,@Inject()注入ctx: Context。
Event 触发器
Event 是最简单的类型:函数不绑定特定触发器,可以直接通过 event 手动触发参数,也可以在平台绑定其他触发器。通过ServerlessTriggerType.EVENT声明:
import { Provide, Inject, ServerlessTrigger, ServerlessTriggerType } from '@midwayjs/core'; import { Context } from '@midwayjs/faas'; @Provide() export class HelloAliyunService { @Inject() ctx: Context; @ServerlessTrigger(ServerlessTriggerType.EVENT) async handleEvent(event: any) { return event; } }HTTP 触发器
阿里云的 HTTP 触发器独立于 API 网关,是另一套直接服务 HTTP 场景的触发器。相比 API 网关,它更易于使用和配置。通过ServerlessTriggerType.HTTP声明,可在装饰器选项中指定path与method:
import { Provide, Inject, ServerlessTrigger, ServerlessTriggerType } from '@midwayjs/core'; import { Context } from '@midwayjs/faas'; @Provide() export class HelloAliyunService { @Inject() ctx: Context; @ServerlessTrigger(ServerlessTriggerType.HTTP, { path: '/', method: 'get', }) async handleHTTPEvent(@Query() name = 'midway') { return `hello ${name}`; } }HTTP 触发器的请求经过 starter 层的特殊处理。查看 packages-serverless/midway-fc-starter/src/index.ts 中onRequest的实现可以发现:当事件的constructor.name为IncomingMessage或EventEmitter时会被识别为 HTTP 模式,随后通过this.framework.wrapHttpRequest(event)把原始请求转换为 Midway 的 Web 上下文;对于 POST/PUT/DELETE 且尚未解析 body 的请求,还会通过raw-body以10mb为上限解析请求体。
API 网关触发器
API 网关在阿里云函数体系中比较特殊:它类似于创建一个无触发器函数,由平台网关绑定到特定路径。使用ServerlessTriggerType.API_GATEWAY声明:
import { Provide, Inject, ServerlessTrigger, ServerlessTriggerType } from '@midwayjs/core'; import { Context } from '@midwayjs/faas'; @Provide() export class HelloAliyunService { @Inject() ctx: Context; @ServerlessTrigger(ServerlessTriggerType.API_GATEWAY, { path: '/api_gateway_aliyun', method: 'post', }) async handleAPIGatewayEvent(@Body() name) { return `hello ${name}`; } }从 starter 源码看,API 网关事件通过event.headers是否存在queryParameters与httpMethod字段来判定,随后同样走wrapHttpRequest路径(见 packages-serverless/midway-fc-starter/src/index.ts)。值得注意的一个实现细节是:API 网关模式返回时会过滤掉content-length头(因为 base64 编码后的长度不正确),并且不支持多个 cookie——当响应含多个set-cookie时只取第一个并输出 warn 日志(见同文件L170-L186)。
Timer 定时触发器
定时任务触发器用于定时执行一个函数。使用ServerlessTriggerType.TIMER声明,事件参数类型为TimerEvent(来自@midwayjs/fc-starter):
import { Provide, Inject, ServerlessTrigger, ServerlessTriggerType } from '@midwayjs/core'; import { Context } from '@midwayjs/faas'; import type { TimerEvent } from '@midwayjs/fc-starter'; @Provide() export class HelloAliyunService { @Inject() ctx: Context; @ServerlessTrigger(ServerlessTriggerType.TIMER) async handleTimerEvent(event: TimerEvent) { this.ctx.logger.info(event); return 'hello world'; } }:::info 温馨提醒,测试函数后请及时关闭触发器自动执行,避免超额扣费。 :::
事件结构:Timer 消息返回的结构如下,在TimerEvent类型中有描述:
{ "triggerTime": new Date().toJSON(), "triggerName": "timer", "payload": "" }在 packages-serverless/midway-fc-starter/src/interface.ts 中,TimerEvent被定义为{ triggerTime: string; triggerName: string; payload: string },与示例结构一一对应。
OSS 触发器
OSS 用于存储资源文件,是阿里云的资源存储产品。当 OSS 中有文件创建、更新时,对应函数被触发执行。使用ServerlessTriggerType.OS声明(注意枚举名是OS,与 OSS 事件对应):
import { Provide, Inject, ServerlessTrigger, ServerlessTriggerType } from '@midwayjs/core'; import { Context } from '@midwayjs/faas'; import type { OSSEvent } from '@midwayjs/fc-starter'; @Provide() export class HelloAliyunService { @Inject() ctx: Context; @ServerlessTrigger(ServerlessTriggerType.OS) async handleOSSEvent(event: OSSEvent) { // xxx } }事件结构:OSS 消息返回的结构如下,在FC.OSSEvent类型中有描述:
{ "events": [ { "eventName": "ObjectCreated:PutObject", "eventSource": "acs:oss", "eventTime": "2017-04-21T12:46:37.000Z", "eventVersion": "1.0", "oss": { "bucket": { "arn": "acs:oss:cn-shanghai:123456789:bucketname", "name": "testbucket", "ownerIdentity": "123456789", "virtualBucket": "" }, "object": { "deltaSize": 122539, "eTag": "688A7BF4F233DC9C88A80BF985AB7329", "key": "image/a.jpg", "size": 122539 }, "ossSchemaVersion": "1.0", "ruleId": "9adac8e253828f4f7c0466d941fa3db81161e853" }, "region": "cn-shanghai", "requestParameters": { "sourceIPAddress": "140.205.128.221" }, "responseElements": { "requestId": "58F9FF2D3DF792092E12044C" }, "userIdentity": { "principalId": "123456789" } } ] }仓库 packages-serverless/midway-fc-starter/src/interface.ts 中SingleOSSEvent与OSSEvent的类型定义与上述 JSON 完全吻合。
MNS 消息触发器
MNS(消息服务)触发器在 OSS 之外的另一类事件源。使用ServerlessTriggerType.MQ声明:
:::info
- 1、阿里云消息队列会对 Topic 和 Queue 产生一定的费用。
- 2、提供的默认消息队列格式为 JSON :::
import { Provide, Inject, ServerlessTrigger, ServerlessTriggerType } from '@midwayjs/core'; import { Context } from '@midwayjs/faas'; import type { MNSEvent } from '@midwayjs/fc-starter'; @Provide() export class HelloAliyunService { @Inject() ctx: Context; @ServerlessTrigger(ServerlessTriggerType.MQ) async handleMNSEvent(event: MNSEvent) { // ... } }事件结构:MNS 消息返回的结构如下,在FC.MNSEvent类型中有描述:
{ "Context": "user custom info", "TopicOwner": "1186202104331798", "Message": "hello topic", "Subscriber": "1186202104331798", "PublishTime": 1550216302888, "SubscriptionName": "test-fc-subscibe", "MessageMD5": "BA4BA9B48AC81F0F9C66F6C909C39DBB", "TopicName": "test-topic", "MessageId": "2F5B3C281B283D4EAC694B7425288675" }值得留意的是,packages-serverless/midway-fc-starter/src/interface.ts 中MNSEvent被定义为一个联合类型:string | MNSStreamEvent | MNSJSONEvent。也就是说 MNS 消息既可能是原始字符串,也可能是流式消息(body+attrs),还可能是上面的 JSON 结构,编写处理逻辑时建议对三种形态做兼容。
触发器配置的归属说明
:::info 触发器的更多配置由于和平台相关,将写在s.yaml中,如定时任务的时间间隔等,更多细节请查看下面的部署段落。 :::
装饰器只负责声明“函数绑定什么类型的触发器、路径与方法是什么”,而触发器的执行细节(定时任务的 cron 表达式、HTTP 触发器的鉴权方式等)全部收敛到 Serverless Devs 的描述文件s.yaml中,下文部署章节会详细展开。
类型定义
FC 的定义由适配器(@midwayjs/fc-starter)导出。为了让ctx.originContext的定义保持正确,需要将类型导入添加到src/interface.ts中:
// src/interface.ts import type {} from '@midwayjs/fc-starter';此外,适配器还提供了各种 Event 类型的定义:
// Event 类型 import type { OSSEvent, MNSEvent, SLSEvent, CDNEvent, TimerEvent, APIGatewayEvent, TableStoreEvent, } from '@midwayjs/fc-starter'; // InitializeContext 类型 import type { InitializeContext } from '@midwayjs/fc-starter';这些类型全部定义在 packages-serverless/midway-fc-starter/src/interface.ts,除上文已经出现的OSSEvent、MNSEvent、TimerEvent外,还包含:
SLSEvent:日志服务(SLS)触发的事件,含parameter、source(endpoint / projectName / logstoreName / shardId 等)、jobName、taskId、cursorTime;CDNEvent:CDN 日志/刷新触发的事件,含事件来源域名resource.domain与事件参数eventParameter;APIGatewayEvent:API 网关入参结构,含path、httpMethod、headers、queryParameters、pathParameters、body、isBase64Encoded;TableStoreEvent:表格存储(TableStore)触发的事件,含Version与Records数组;InitializeContext:FC 初始化上下文,含requestId、credentials(临时密钥)、function(名称、handler、内存、超时)、service(名称、日志项目/库、版本)、region、accountId、logger等字段。
本地开发
HTTP 触发器和 API 网关类型可以通过本地npm run dev以和传统应用类似的方式进行本地开发;其他类型的触发器本地无法使用 dev 开发,只能通过运行npm run test进行测试执行。这是因为 HTTP 类触发器在底层会走wrapHttpRequest生成完整的 Web 上下文(见 packages/faas/src/framework.ts 中MidwayFaaSFramework对developmentRun模式的处理),而事件类触发器没有对应的 HTTP 服务形态。
本地测试
和传统应用测试类似,使用createFunctionApp方法创建函数 app,使用close方法关闭。mockContext方法(来自@midwayjs/fc-starter)用来模拟一个 FC Context 数据结构,可以自定义传递一个类似的结构或者修改部分数据:
import { Application, Context, Framework } from '@midwayjs/faas'; import { mockContext } from '@midwayjs/fc-starter'; import { createFunctionApp } from '@midwayjs/mock'; describe('test/hello_aliyun.test.ts', () => { it('should get result from event trigger', async () => { // create app const app: Application = await createFunctionApp<Framework>(join(__dirname, '../'), { initContext: mockContext(), }); // ... await close(app); }); });如果需要覆盖部分平台信息,可以将mockContext()与自定义对象合并,例如修改函数名称与 handler:
import { Application, Context, Framework } from '@midwayjs/faas'; import { mockContext } from '@midwayjs/fc-starter'; import { createFunctionApp } from '@midwayjs/mock'; describe('test/hello_aliyun.test.ts', () => { it('should get result from event trigger', async () => { // create app const app: Application = await createFunctionApp<Framework>(join(__dirname, '../'), { initContext: Object.assign(mockContext(), { function: { name: '***', handler: '***' } }), }); // ... await close(app); }); });mockContext的默认结构定义在 packages-serverless/midway-fc-starter/src/mock.ts,包含 requestId、STS 临时凭证、函数信息(名称 / handler / 内存 128 / 超时 10s)、服务信息(名称 / 日志项目 / 版本)、region(默认 cn-shanghai)、accountId 与 logger。该 mock 结构在 starter 内部也作为createDefaultMockContext使用(见 packages-serverless/midway-fc-starter/src/index.ts),保证本地初始化的上下文与线上结构一致。
Event 触发器测试
通过getServerlessInstance获取类实例,直接调用实例方法、传入参数进行测试:
import { HelloAliyunService } from '../src/function/hello_aliyun'; describe('test/hello_aliyun.test.ts', () => { it('should get result from event trigger', async () => { // ... const instance = await app.getServerlessInstance<HelloAliyunService>(HelloAliyunService); expect(await instance.handleEvent('hello world')).toEqual('hello world'); // ... }); });HTTP 触发器测试
和应用测试相同,通过createFunctionApp创建函数 app,通过createHttpRequest方式进行测试:
import { HelloAliyunService } from '../src/function/hello_aliyun'; describe('test/hello_aliyun.test.ts', () => { it('should get result from http trigger', async () => { // ... const result = await createHttpRequest(app).get('/').query({ name: 'zhangting', }); expect(result.text).toEqual('hello zhangting'); // ... }); });API 网关测试
和 HTTP 测试相同,通过createFunctionApp创建函数 app,通过createHttpRequest方式进行测试:
import { createHttpRequest } from '@midwayjs/mock'; describe('test/hello_aliyun.test.ts', () => { it('should get result from http trigger', async () => { // ... const result = await createHttpRequest(app).post('api_gateway_aliyun').send({ name: 'zhangting', }); expect(result.text).toEqual('hello zhangting'); // ... }); });Timer 触发器测试
和 HTTP 测试不同,通过createFunctionApp创建函数 app,通过getServerlessInstance获取整个类的实例从而调用到特定方法测试。可以通过mockTimerEvent方法快速创建平台传入的结构:
import { HelloAliyunService } from '../src/function/hello_aliyun'; import { mockTimerEvent } from '@midwayjs/fc-starter'; describe('test/hello_aliyun.test.ts', () => { it('should get result from timer trigger', async () => { // ... const instance = await app.getServerlessInstance<HelloAliyunService>(HelloAliyunService); expect(await instance.handleTimerEvent(mockTimerEvent())).toEqual('hello world'); // ... }); });OSS 触发器测试
和 HTTP 测试不同,通过createFunctionApp创建函数 app,通过getServerlessInstance获取整个类的实例从而调用到特定方法测试。可以通过mockOSSEvent方法快速创建平台传入的结构:
import { HelloAliyunService } from '../src/function/hello_aliyun'; import { mockOSSEvent } from '@midwayjs/fc-starter'; describe('test/hello_aliyun.test.ts', () => { it('should get result from oss trigger', async () => { // ... const instance = await app.getServerlessInstance<HelloAliyunService>(HelloAliyunService); expect(await instance.handleOSSEvent(mockOSSEvent())).toEqual('hello world'); // ... }); });MNS 触发器测试
和 HTTP 测试不同,通过createFunctionApp创建函数 app,通过getServerlessInstance获取整个类的实例从而调用到特定方法测试。可以通过mockMNSEvent方法快速创建平台传入的结构:
import { HelloAliyunService } from '../src/function/hello_aliyun'; import { mockMNSEvent } from '@midwayjs/fc-starter'; describe('test/hello_aliyun.test.ts', () => { it('should get result from oss trigger', async () => { // ... const instance = await app.getServerlessInstance<HelloAliyunService>(HelloAliyunService); expect(await instance.handleMNSEvent(mockMNSEvent())).toEqual('hello world'); // ... }); });除上述事件外,packages-serverless/midway-fc-starter/src/mock.ts 还提供了mockCDNEvent、mockSLSEvent、mockTableStoreEvent,分别用于快速构造 CDN、日志服务 SLS 与表格存储 TableStore 的触发事件,覆盖了 fc-starter 接口定义中的全部事件类型。这些 mock 数据的字段结构均与 packages-serverless/midway-fc-starter/src/interface.ts 中的类型定义保持一致。
纯函数部署(内置运行时)
以下将简述如何使用 Serverless Devs 部署到阿里云函数。
1、确认启动器
在项目根目录的f.yml的provider段落处确保 starter 为@midwayjs/fc-starter:
provider: name: aliyun starter: '@midwayjs/fc-starter'starter指向的就是仓库中的 packages-serverless/midway-fc-starter 包,其导出的BootstrapStarter会在启动时根据initializeMethodName(默认initializer)与handlerName生成平台可调用的函数出口(见 packages-serverless/midway-fc-starter/src/index.ts)。
2、安装 Serverless Devs 工具
阿里云使用 Serverless Devs 工具进行函数部署。你可以将其安装到全局:
$ npm install @serverless-devs/s -g参考 Serverless Devs 官方文档中“密钥配置”章节完成云账号密钥的配置。
3、编写一个 Serverless Devs 描述文件
在根目录创建一个s.yaml,添加以下内容:
edition: 1.0.0 name: "midwayApp" # 项目名称 access: "default" # 秘钥别名 vars: service: name: fc-build-demo description: 'demo for fc-deploy component' services: project-0981cd9b07: component: devsapp/fc props: region: cn-hangzhou service: ${vars.service} function: name: hello # 函数名 handler: helloHttpService.handleHTTPEvent codeUri: '.' initializer: helloHttpService.initializer customDomains: - domainName: auto protocol: HTTP routeConfigs: - path: /* serviceName: ${vars.service.name} functionName: helloHttpService-handleHTTPEvent triggers: - name: http type: http config: methods: - GET authType: anonymous每个新增的函数都需要调整s.yaml文件。为此,Midway 提供了一个@midwayjs/serverless-yaml-generator工具,用来将装饰器函数信息写入s.yaml:
{ "scripts": { + "generate": "serverless-yaml-generator", }, "devDependencies": { + "@midwayjs/serverless-yaml-generator": "^1.0.0", }, }通过执行下面的命令,可以将现有函数信息填充到s.yaml中,并生成入口文件,方便排查问题:
$ npm run generate工具将以函数名作为 key 在s.yaml中查找配置,其行为规则如下:
- 如果存在函数,则会覆盖特定字段,比如
handler、http 触发器的methods; - 如果不存在函数,则会添加一个新函数;
- 工具不会写入 http 的路由方法,为了简化后续更新,可以提供一个
/*路由(如示例中的routeConfigs配置)。
官方推荐的做法是:只在装饰器中定义基础函数名、函数 handler,以及基础触发器信息(比如 http 触发器的 path 和 method),其余配置都写在yaml中。s.yaml的完整配置较为复杂,具体请参考 Serverless Devs 官方“描述文件规范”文档。
4、编写一个部署脚本
由于部署有构建、拷贝等多个步骤,我们可以编写部署脚本统一这个过程。比如在项目根目录新建一个deploy.sh文件,内容如下:
#!/bin/bash set -e # 构建产物目录 export BUILD_DIST=$PWD/.serverless # 构建开始时间,单位毫秒 export BUILD_START_TIME=$(date +%s%3N) echo "Building Midway Serverless Application" # 打印当前目录 cwd echo "Current Working Directory: $PWD" # 打印结果目录 BUILD_DIST echo "Build Directory: $BUILD_DIST" # 安装当前项目依赖 npm i # 执行构建 ./node_modules/.bin/tsc || return 1 # 生成入口文件 ./node_modules/.bin/serverless-yaml-generator || return 1 # 如果 .serverless 文件夹存在,则删除后重新创建 if [ -d "$BUILD_DIST" ]; then rm -rf $BUILD_DIST fi mkdir $BUILD_DIST # 拷贝 dist、 *.json、*.yml 到 .serverless 目录 cp -r dist $BUILD_DIST cp *.yaml $BUILD_DIST 2>/dev/null || : cp *.json $BUILD_DIST 2>/dev/null || : # 移动入口文件到 .serverless 目录 mv *.js $BUILD_DIST 2>/dev/null || : # 进入 .serverless 目录 cd $BUILD_DIST # 安装线上依赖 npm install --production echo "Build success" # 在 .serverless 目录进行部署 s deploy可以将这个deploy.sh文件放到package.json的deploy指令中,后续部署执行npm run deploy即可:
{ "scripts": { "deploy": "sh deploy.sh" } }:::tip
- 1、
deploy.sh只测试了 mac,其余平台可以自行调整 - 2、脚本内容可以根据业务逻辑自行调整,比如拷贝的文件等 :::
脚本的流程本质上是:安装依赖 →tsc编译 → 生成s.yaml与入口文件 → 组装.serverless产物目录 → 安装生产依赖 → 在该目录执行s deploy。它把“构建产物目录”固定为.serverless,部署时只需要把编译后的 JS、配置与生产依赖打进 zip 交给平台即可。
自定义运行时部署
1、创建项目
自定义运行时可以使用标准项目来部署,由于需要提供 9000 端口,需要创建 Midway koa / Egg / Express 项目。初始化项目请参考 创建第一个应用。
2、调整端口
为了避免影响本地开发,我们仅在入口bootstrap.js处增加端口:
const { Bootstrap } = require('@midwayjs/bootstrap'); // 显式以组件方式引入用户代码 Bootstrap.configure({ globalConfig: { koa: { port: 9000, } } }).run()不同的框架修改端口请参考:
- koa 修改端口
- Egg 修改端口
- Express 修改端口
3、平台部署配置
自定义运行时在 FC 控制台的部署要点如下:
- 1、选择运行环境,比如
Node.js 18 - 2、选择代码上传方式,比如可以本地打 zip 包上传
- 3、启动命令指定
node bootstrap.js - 4、监听端口
9000
配置完成之后,上传压缩包即可部署完成。这一方式的核心是:平台提供 Node.js 系统镜像,由你的bootstrap.js拉起完整的 Midway Web 应用并监听 9000 端口,平台再将外部请求转发到该端口,从而实现“标准应用”在函数计算上的运行,与内置运行时的纯函数形态互补。
小结
至此,Midway 部署到阿里云函数计算的完整链路已经打通,核心要点可以归纳为四条:
- 选型先决:内置运行时适合纯函数(无端口、zip 部署);自定义运行时 / 自定义容器适合标准 Web 应用,必须监听 9000 端口。
- 触发器编码:统一使用
@ServerlessTrigger声明 Event / HTTP / API 网关 / Timer / OSS / MNS 触发器,事件结构与类型定义由@midwayjs/fc-starter提供(见 packages-serverless/midway-fc-starter/src/interface.ts)。 - 本地可测:借助
@midwayjs/mock的createFunctionApp/createHttpRequest与 fc-starter 的mockContext、mockTimerEvent、mockOSSEvent、mockMNSEvent等工具,在本地即可还原平台事件结构完成单测(见 packages-serverless/midway-fc-starter/src/mock.ts)。 - 部署收敛:平台相关的触发器细节统一写入
s.yaml,由 Serverless Devs 执行部署;serverless-yaml-generator自动同步装饰器信息,deploy.sh统一完成构建、组装产物与发布。
在仓库中,如果你希望进一步验证这些机制,可以阅读 packages-serverless/midway-fc-starter/test/index.test.ts:它直接实例化BootstrapStarter,分别以 Event 事件、API 网关事件和 HTTP 请求(通过EventEmitter模拟)调用initializer、apigw、http等函数出口,并断言响应体、状态码与响应头,是理解 fc-starter 运行时行为的直观样例。此外,serverless 系列文档 与 serverless 测试文档 可作为进一步深入学习的入口。
- 后端
- 微服务
- 云原生
【免费下载链接】midway
🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈
相关推荐
Midway 部署阿里云函数计算(FC)实战指南:触发器开发、本地测试与 Serverless Devs 部署
Midway 部署阿里云函数计算(FC)实战指南:触发器开发、本地测试与 Serverless Devs 部署 本文以 Midway 的 Serverless
后端微服务云原生使用 @midwayjs/serverless-fc-starter 在阿里云函数计算 FC 上运行 Midway 应用
使用 @midwayjs/serverless fc starter 在阿里云函数计算 FC 上运行 Midway 应用 本指南围绕 packages serv
后端微服务云原生终极指南:如何将AutoTrain Advanced模型快速部署到阿里云函数计算
终极指南:如何将AutoTrain Advanced模型快速部署到阿里云函数计算 AutoTrain Advanced是一款强大的AI模型自动训练与部署工具,能
机器学习深度学习NLP计算机视觉微调后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考