
Gatsby 开发环境 API 代理配置指南proxy 与 developMiddleware 实战解析【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby在 Gatsby 开发环境中前后端分离架构下最常见的痛点之一就是浏览器中的fetch请求如何安全、无跨域地打到后端 API 服务。Gatsby 提供了两套互补的机制基于gatsby-config.js中proxy字段的简单请求转发以及通过developMiddleware暴露 Express 开发服务器实例的高级代理/中间件方案。本文将基于 Gatsby 官方文档与仓库源码系统讲解这两种方案的使用方法、底层实现原理与生产环境注意事项读完即可在你的 Gatsby 项目中配置 API 代理。本文对应的原始文档为 docs/docs/api-proxy.md所有源码依据均来自当前仓库 packages/gatsby 下的实现。为什么需要 API 代理在典型的 Gatsby 项目开发流程中前端 React 应用运行在gatsby develop启动的本地开发服务器上默认http://localhost:8000而后端 API 通常部署在另一台主机或另一个端口例如http://dev-mysite.com或http://localhost:9000。如果前端直接向这些地址发起请求会遭遇跨域CORS问题同时还需要在代码中硬编码环境相关的 URL。Gatsby 的解法是让开发服务器充当请求转发的中转站——当浏览器请求一个开发服务器上不存在的静态资源路径时开发服务器将该请求原样转发给配置中指定的 API 服务器再把响应流式返回给浏览器。这样前端代码里只需要写相对路径如fetch(/api/todos)既绕开了跨域限制也让代码在不同环境之间更加可移植。方式一使用proxy配置字段基础用法要告诉开发服务器把未知请求代理到你的 API 服务器只需在 gatsby-config.js 中添加一个proxy字段。它支持两种形态单个代理对象或者由多个代理对象组成的数组。单个代理module.exports { proxy: { prefix: /api, url: http://dev-mysite.com, }, }多个代理数组形式module.exports { proxy: [ { prefix: /api, url: http://dev-mysite.com, }, { prefix: /api2, url: http://dev2-mysite.com, }, ], }两个关键字段的含义prefix需要被代理的路径前缀例如/api。所有以该前缀开头的未知请求都会被转发url目标 API 服务器的地址例如http://dev-mysite.com。工作原理配置的真实生效逻辑位于 packages/gatsby/src/utils/start-server.ts。从源码可以看到Gatsby 在启动开发服务器时会从配置状态中取出proxy对其中的每一项注册一个 Express 路由// Set up API proxy. if (proxy) { proxy.forEach(({ prefix, url }) { app.use(${prefix}/*, (req, res) { const proxiedUrl url req.originalUrl ... req .pipe( got .stream(proxiedUrl, { headers, method: method as Method, decompress: false, }) ... ) .pipe(res) }) }, cors()) }关键点在于转发地址是url req.originalUrl——也就是http://dev-mysite.com加上请求的原始路径。因此当你在开发环境下fetch(/api/todos)时开发服务器会识别出它不是一个静态资源并将请求代理到http://dev-mysite.com/api/todos作为回退fallback处理。整个请求以流式stream方式转发客户端请求流被 pipe 到后端后端响应头与状态码被原样写回再以流式返回给浏览器代理失败时如后端不可达则会返回 500 并向终端报告Error when trying to proxy request ... to ...。值得注意的是源码中在注册代理路由时还附加了cors()中间件说明该代理链路本身已考虑了跨域响应头的处理。配置校验与类型约束proxy的合法性由配置校验 schema 保证见 packages/gatsby/src/joi-schemas/joi.tsproxy: Joi.array() .items( Joi.object().keys({ prefix: Joi.string().required(), url: Joi.string().required(), }) ) .single(),这意味着prefix与url均为必填字符串同时支持.single()即配置一个对象或一个数组都会被接受。TypeScript 侧的类型定义也保持一致packages/gatsby/index.d.ts 中的type Proxy以及proxy?: Proxy | Proxy[]字段并在 packages/gatsby/src/utils/merge-gatsby-config.ts 的配置输入类型中体现。注意仅开发环境生效proxy只在开发模式gatsby develop下起作用它由 start-server.ts 中读取并注册。生产构建gatsby build不会应用该配置因此在生产环境中你需要自行确保/api/todos这类路径指向正确的位置——例如通过网关、反向代理或同源部署将 API 路由与静态站点对齐。方式二使用developMiddleware进行高级代理当你需要更细粒度、更灵活的代理规则例如路径重写、按条件过滤、转发到本地函数服务时简单的前缀转发就不够用了。Gatsby 将底层的Express.js 开发服务器实例暴露给了站点的gatsby-config.js你可以在developMiddleware回调中按需添加 Express 中间件。基础用法下面的示例使用http-proxy-middleware包v1.x.x 版本将所有/.netlify/functions/开头的请求代理到本地http://localhost:9000同时通过pathRewrite将路径前缀去掉const { createProxyMiddleware } require(http-proxy-middleware) //v1.x.x // Use implicit require for v0.x.x of http-proxy-middleware // const proxy require(http-proxy-middleware) // be sure to replace createProxyMiddleware with proxy where applicable module.exports { developMiddleware: app { app.use( /.netlify/functions/, createProxyMiddleware({ target: http://localhost:9000, pathRewrite: { /.netlify/functions/: , }, }) ) }, }底层调用链developMiddleware的实现同样位于 packages/gatsby/src/utils/start-server.ts// Expose access to app for advanced use cases const { developMiddleware } store.getState().config if (developMiddleware) { developMiddleware(app) }即在注册静态资源、代理路由等默认中间件之前Gatsby 会先取出配置中的developMiddleware函数并调用它将 Expressapp实例作为参数传入。你可以在该回调中对app执行任意app.use(...)、app.get(...)等操作从而按需注入中间件。developMiddleware与proxy一样只在gatsby develop时生效。从配置 schema 看它被校验为函数类型developMiddleware: Joi.func()见 joi.ts类型定义中同样注明“其用途是添加代理与中间件”index.d.ts。处理自签名证书如果你代理的目标是使用自签名证书self-signed certificates的本地 APIhttp-proxy-middleware默认会校验 TLS 证书并拒绝连接。此时需要将secure选项设为falseconst { createProxyMiddleware } require(http-proxy-middleware) //v1.x.x // Use implicit require for v0.x.x of http-proxy-middleware // const proxy require(http-proxy-middleware) // be sure to replace createProxyMiddleware with proxy where applicable module.exports { developMiddleware: app { app.use( /.netlify/functions/, createProxyMiddleware({ target: http://localhost:9000, secure: false, // Do not reject self-signed certificates. pathRewrite: { /.netlify/functions/: , }, }) ) }, }该选项在源码注释中明确标注“Do not reject self-signed certificates”仅应在开发环境访问受信任的本地服务时使用切勿在生产环境盲目关闭证书校验。两种方案的对比与选型维度proxy字段developMiddleware配置位置gatsby-config.js 顶层proxy字段gatsby-config.js 顶层developMiddleware函数配置形态单个对象或对象数组接收 Expressapp的回调函数能力范围仅按prefix前缀转发地址为url originalUrl可注入任意 Express 中间件支持路径重写、条件过滤等生效范围仅gatsby develop仅gatsby develop适用场景简单的前后端分离开发Netlify Functions 本地联调、复杂路由重写等高级需求从源码结构看proxy是 Gatsby 内置的轻量转发能力不依赖第三方代理库而developMiddleware是面向“需要更细粒度/灵活访问开发服务器”的场景设计的扩展点。如果你的需求只是把/api请求转发到远端服务器优先使用proxy如果你需要路径重写、自定义请求头处理或对接本地函数运行环境则选择developMiddleware。生产环境的补充说明需要再次强调以上两种机制都只影响gatsby develop。生产环境中proxy配置不会被打包进静态站点developMiddleware也不会在gatsby build时执行。为了让/api/todos这类相对路径在生产环境同样可用你需要将 API 与静态站点部署在同一域名下通过反向代理/Nginx 等将/api转发到后端服务或在代码中根据环境注入 API 基础地址例如通过环境变量或使用服务端网关或托管平台自带的代理能力。参考资料官方文档docs/docs/api-proxy.md本文原始依据生命周期概览Gatsby Lifecycle APIs对应原文档开头的相关链接 docs/docs/conceptual/gatsby-lifecycle-apis.md代理与中间件的核心实现packages/gatsby/src/utils/start-server.ts配置校验 schemapackages/gatsby/src/joi-schemas/joi.ts配置输入类型与合并逻辑packages/gatsby/src/utils/merge-gatsby-config.tsTypeScript 类型声明packages/gatsby/index.d.ts【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考