news 2026/10/9 7:39:22

Midway 阿里云函数计算(FC)部署实战:触发器开发、Serverless Devs 部署与自定义运行时接入

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Midway 阿里云函数计算(FC)部署实战:触发器开发、Serverless Devs 部署与自定义运行时接入
  • 后端
  • 微服务
  • 云原生

【免费下载链接】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. 🌈

项目地址:https://gitcode.com/gh_mirrors/mi/midway
点击查看免费下载

本篇技术指南围绕 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 部署到阿里云函数计算的完整链路已经打通,核心要点可以归纳为四条:

  1. 选型先决:内置运行时适合纯函数(无端口、zip 部署);自定义运行时 / 自定义容器适合标准 Web 应用,必须监听 9000 端口。
  2. 触发器编码:统一使用@ServerlessTrigger声明 Event / HTTP / API 网关 / Timer / OSS / MNS 触发器,事件结构与类型定义由@midwayjs/fc-starter提供(见 packages-serverless/midway-fc-starter/src/interface.ts)。
  3. 本地可测:借助@midwayjs/mock的createFunctionApp/createHttpRequest与 fc-starter 的mockContext、mockTimerEvent、mockOSSEvent、mockMNSEvent等工具,在本地即可还原平台事件结构完成单测(见 packages-serverless/midway-fc-starter/src/mock.ts)。
  4. 部署收敛:平台相关的触发器细节统一写入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. 🌈

项目地址:https://gitcode.com/gh_mirrors/mi/midway
点击查看免费下载

相关推荐

上一篇:tsParticles Full Bundle 完整功能包使用指南:用 loadFull 一键启用全部官方特性
下一篇:CANN ops-math Lerp 算子全解析:从 aclnnLerp 接口到 Ascend 内核实现

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 7:39:11

Brython 文件读取实战:open() 与 browser.ajax 双方案详解

编程语言语言运行时编译器前端 【免费下载链接】brython Brython (Browser Python) is an implementation of Python 3 running in the browser 项目地址&#xff1a; https://gitcode.com/gh_mirrors/br/brython 点击查看 免费下载 导读 本文基于 Brython 官方 Cookbook 中的…

作者头像 李华
网站建设 2026/10/9 7:37:14

Loop:三秒摆好窗口布局的免费开源 macOS 窗口管理

Loop&#xff1a;三秒摆好窗口布局的免费开源 macOS 窗口管理 【免费下载链接】Loop Window management made elegant. 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 你正在打字&#xff0c;想把参考窗口挪到当前窗口旁边。抓起标题栏、拖动、再对齐几次&…

作者头像 李华
网站建设 2026/10/9 7:33:21

AI审美提升指南:视觉拆解与提示词精修两大核心技能

1. 为什么“AI审美”成了当下最值得聊的话题1.1 从“能用”到“好看”&#xff0c;中间隔着一道审美鸿沟最近半年&#xff0c;我身边做设计、做内容、做产品的朋友几乎都在讨论同一件事&#xff1a;AI生成的东西&#xff0c;怎么总是差那么一口气&#xff1f;明明提示词写得很详…

作者头像 李华
网站建设 2026/10/9 7:32:41

Python GIL 深度解析:多线程为何变慢?性能实测与突围方案

多线程加速是不是神话&#xff1f;这是每个 Python 开发迟早会在某个深夜撞上的问题。你郑重地写下ThreadPoolExecutor&#xff0c;把十个 CPU 密集型任务丢进去&#xff0c;结果在八核机器上跑出了比单线程还慢的耗时——那一刻你第一次听见"GIL"这个名字&#xff0…

作者头像 李华
网站建设 2026/10/9 7:31:40

开源多模态视频模型 MiniMax H3 部署与推理优化实践

搞视频AI的人大概都有一个共同的痛点&#xff1a;生成一段视频要抽帧、分析画面、转换文本、对齐音频、再加字幕&#xff0c;每一步都要接不同的模型&#xff0c;管线长到怀疑人生。上个月我在处理一个内部需求时&#xff0c;把开源多模态视频模型 MiniMax H3 视频工作室整套流…

作者头像 李华