
后端微服务云原生【免费下载链接】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 的函数式全栈开发模式时团队最先遇到的往往是两个基础问题代码应该放在哪里、前端到底可以引用什么。本文以 site/docs/functional/workspace.md 为主线完整梳理 Midway 推荐的src/server/src/web工作区布局、默认目录约定、前端可引用边界及其底层原理并结合midwayjs/web-bridge的 Vite/Rspack 插件源码与add-functional-web-routing-api设计方案给出可落地的目录自定义与构建配置方案。推荐目录一套前后端共存的工程骨架Midway 函数式全栈模式推荐采用前后端同仓、按目录分区的组织方式最小骨架如下src ├── server │ ├── index.ts # Midway 服务端入口也可命名为 configuration.ts │ └── api │ └── user.api.ts # 用户 API 定义defineApi └── web ├── main.tsx # 前端启动入口 ├── app.tsx # 前端应用根组件 └── api └── client.ts # 前端 API 客户端创建这份结构与midwayjs/api-bridge的 README 中推荐的工程布局一致packages/api-bridge/README.md 中同样是src/server/api/user.api.ts与src/web/main.tsx的组合。仓库内samples/functional-api-service纯后端函数式服务与samples/functional-api-hybrid装饰器 函数式混用两个示例均遵循API 定义放src/api、入口放bootstrap.ts/configuration.ts的同构思路可作为最小可运行参考。默认约定三个目录常量工作区划分对应三个默认目录约定serverDir默认src/server承载 Midway 后端运行时、defineApi实现与 handlerwebDir默认src/web承载 React 或 Vue 前端应用团队二选一apiDir默认src/server/api作为 API 定义的单一真相源。需要强调的是以上均为约定而非强制。add-functional-web-routing-api设计文档中明确将其描述为最小两层结构路径可配置以下为默认示例见 openspec/changes/add-functional-web-routing-api/design.md 的 Workspace Topology 一节因此团队完全可以按自身习惯调整。单一入口导出规范apiDir作为 API 定义来源建议提供统一的入口文件前后端都从这里导入// src/server/api/index.ts export { userApi } from ./user.api; export { orderApi } from ./order.api; export type * from ./user.api; export type * from ./order.api;该入口只导出defineApi结果与类型禁止导出 IoC 实例或运行时对象从而保证前后端拿到的是同一份语义来源。前端可引用 / 不可引用web-safe 边界这是工作区规划中最重要的纪律直接决定浏览器 bundle 是否会意外混入服务端代码前端可以引用src/server/api导出的 API 定义类型和 schema如 zod 等 schema 常量、纯类型导出。前端不要引用Node-only 模块fs/path/net服务端运行时代码handler 内部实现细节。对应地add-functional-web-routing-api设计文档的 Web-safe Boundary Rules 一节给出了更完整的边界清单openspec/changes/add-functional-web-routing-api/design.md允许导出defineApi声明对象、schema 常量、纯类型导出 禁止进入 web bundleuseInject、Inject、Config等 Midway 运行时依赖fs/path/process等 Node 专属模块以及 handler 函数体及其运行时闭包引用。违规时编译层会给出明确处理dev 阶段抛编译错误并定位到具体 API 文件与字段build 阶段直接阻断 web 构建。设计文档还为此定义了MW_API_BRIDGE_UNSAFE_IMPORT等桥接层错误码用于标注server runtime 依赖泄露到 web这一类问题。为什么这样划分单一真相源核心原因在于src/server/api/*.api.ts既是服务端路由契约也是前端类型来源。defineApi声明的路由同时携带 method、path、input/output schema 与 handler 元信息见add-functional-web-routing-api设计文档的 Definition Layer 描述。前端直接导入src/server/api由编译层重写调用而不是各自维护一份重复的 contracts 文件。统一这一层之后减少重复定义前后端不再各写一份接口清单消除联调偏差schema 变更会即时反映到前端类型编译期即可发现不匹配实现单一真相源Single Source of Truth这是设计文档 Decision 11 的核心主张openspec/changes/add-functional-web-routing-api/design.md。midwayjs/api-bridge的 README 也通过 Single Source Entry 一节演示了这套协作方式前端src/web/api/client.ts直接import { userApi } from /server/api再用createClient包装成可调用的类型化客户端。开发和发布统一入口、分离产物开发期与发布期采用两套策略开发期建议只暴露一个npm run dev入口。dev runner 内部统一拉起 server watcher暴露 API 定义源、web dev server消费server/api导入重写结果和 bridge compiler内存重写调用与类型映射。API 变更后由 bridge compiler 触发增量更新与 HMR。这就是设计文档 Decision 17单一 Dev 入口的落地方式——用户不需要手动分别启动 server 与 web 的 dev 进程openspec/changes/add-functional-web-routing-api/design.md。发布期仍然前后端分离产物和部署。server 与 web 产物分开构建web 只消费提取后的 web-safe 中间产物CI/CD 建议串行执行server-api-check - server-build - web-build设计文档 Decision 12构建与发布解耦。web/api目录如何自定义src/web/api只是推荐目录不是强制。你可以改成src/client/apisrc/web/sdk或任意团队习惯的目录改目录时关键是保持两件事一致你的前端 client 文件导入路径指向新的前端侧目录构建插件里的apiDir服务端 API 定义目录即src/server/api的位置。如果你同时修改了 server 根目录serverDir还需要同步调整devPlugin的baseDir保证 dev 入口能正确定位服务端代码。Vite 示例把服务端 API 目录改为src/contracts/apiapiPlugin({ root: process.cwd(), apiDir: src/contracts/api, target: both, });Rspack 示例createApiRspackRule({ root: process.cwd(), apiDir: src/contracts/api, });apiPlugin与createApiRspackRule均由 packages/web-bridge 包提供分别从midwayjs/web-bridge/vite与midwayjs/web-bridge/rspack导入完整用法见 packages/web-bridge/README.md。从源码看apiDir到底做了什么要理解改apiDir为什么必须同步前端导入路径需要看编译插件的实现。Vite 插件虚拟模块与边界判定在 packages/web-bridge/src/vite.ts 中apiPlugin接收ApiPluginOptionsexport interface ApiPluginOptions { root?: string; apiDir: string; target?: client | ssr | both; }几个关键实现点apiDir是必选项插件入口会校验options.apiDir缺失时直接抛出带示例的错误vite.ts中apiPlugin起始处target决定转换范围target client只做浏览器端转换ssr只做 SSR 转换both两者都启用边界判定插件在resolveId阶段解析导入路径只有当解析后的文件startsWith(apiDir)且源码包含可静态解析的defineApi时才将其重定向到虚拟模块 ID\0midway-api:前缀HMR 联动handleHotUpdate中当apiDir内的 API 文件变更时插件会使对应虚拟模块失效并触发增量更新——这正是API 变更后前端类型自动刷新的实现基础静态解析transformDefineApiSource只做纯文本层面的结构扫描跳过字符串与注释、按括号深度切分提取每个导出 API 的 prefix 与路由表不执行 handler 代码这也是 web-safe 边界的编译期保证。Rspack 插件loader 重写在 packages/web-bridge/src/rspack.ts 中createApiRspackRule生成一条enforce: pre的规则将apiDir目录内的\.[cm]?[jt]sx?$文件交给midwayjs/web-bridge/rspackloader 处理apiRspackLoader内部同样先做apiDir路径判定inApiDir与defineApi内容判定shouldTransform命中后才把源码重写为 web-safe 的 API 契约代码。由此可见apiDir不仅是服务端代码放哪的目录约定它同时被 Vite/Rspack 编译插件用作转换范围的硬边界。如果前端导入路径与插件apiDir不一致转换就不会生效前端拿到的将是原始 server 源码——这正是文档强调两件事必须一致的底层原因。运行时客户端边界之外的正常调用前端侧的调用由midwayjs/api-bridge的createClient完成它只依赖编译期提取出的契约与 HTTP 传输适配器不触碰 Midway 运行时// src/web/api/client.ts import { createClient } from midwayjs/api-bridge; import { userApi } from /server/api; export const api createClient( { user: userApi, }, { basePath: /api, } ); // 直接调用类型由 defineApi 推导 await api.user.getUser({ params: { id: 1 } });默认使用fetch作为 HTTP adapter浏览器与 Node 18 可直接使用需要 axios/tRPC 等实现时传入adapter即可详见 packages/api-bridge/README.md。这也呼应了设计文档 Decision 14/14A前端以 direct-like 方式调用底层自动完成 method/path/序列化与 HTTP 请求发送而 client runtime 统一沉淀在midwayjs/api-bridge避免多框架重复实现。一个可运行的后端示例如果想先验证defineApi的书写形态仓库中的samples/functional-api-hybrid提供了装饰器 函数式路由共存的最小示例samples/functional-api-hybrid/README.md其中函数式路由的声明方式如下samples/functional-api-hybrid/src/api/functional.api.tsimport { defineApi, useInject } from midwayjs/core/functional; export const functionalApi defineApi(/functional, api ({ hello: api .get(/hello) .meta({ routerName: functionalHello }) .handle(async () { const greetingService await useInject{ format: (source: decorator | functional) string; }(greetingService); return { source: functional, message: greetingService.format(functional), }; }), }));注意 handler 内通过useInject获取依赖与 hooks 风格保持一致设计文档 Decision 8IoC 连续性采用 hooks-first。该示例构建启动后监听http://127.0.0.1:7001并使用全局前缀/api装饰器路由与函数式路由可同时访问验证两类声明最终都进入统一路由收集与冲突检测流程设计文档 Decision 4统一路由表。小结Midway 全栈工作区规划可以概括为三句话代码按src/server与src/web分区放置src/server/api是前后端共享的单一真相源前端只能通过编译期转换消费 API 定义与类型绝不能引入 Node 专属模块与服务端运行时。在此基础上serverDir/webDir/apiDir都是可配置的约定改目录时保持前端 client 导入路径与构建插件apiDir一致即可Vite 用apiPlugin、Rspack 用createApiRspackRule修改 server 根目录时再同步调整devPlugin的baseDir就能获得开发期一键启动、发布期前后端分离产物的完整工程体验。赞分享后端微服务云原生【免费下载链接】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 修改源码目录与编译目录src/dist 自定义实战指南Midway 修改源码目录与编译目录src/dist 自定义实战指南 在 Midway 项目的默认约定中TypeScript 源码位于 src 目录编译后端微服务云原生WXT 项目结构完全指南目录约定、src/ 目录迁移与自定义配置WXT 项目结构完全指南目录约定、src/ 目录迁移与自定义配置 WXT 采用严格的项目结构约定来组织 Web Extension 工程本文是该框架的官方项前端开发工具构建工具插件系统Baserow Helm Chart 实战指南Kubernetes 全栈部署、域名路由、按需 TLS 与云厂商适配Baserow Helm Chart 实战指南Kubernetes 全栈部署、域名路由、按需 TLS 与云厂商适配 Baserow 是基于 Django 与文档教程上一篇十分钟搭好自己的 brd 文件查看器OpenBoardView 本地跑起来一键找到元件下一篇AMCT 大模型 GPTQ 仅权重量化实战指南配置、原理与 PPL 精度评估创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考