Skip to content

基于 vercel 边缘函数解决 vercel.json 配置的反向代理方案失效的新方案

之前的方案没用了。被迫用新的方案实现接口的反向代理。

无法在生产环境内给接口实现反向代理的旧方案

直接给 vercel.json 写配置,不能实现反向代理了。

无法实现反向代理的写法
json
{
	"rewrites": [
		{
			"source": "/api/:path*",
			"destination": "http://8.154.39.107:10001/:path*"
		}
	]
}

基于 vercel 边缘函数实现的代理

首先阅读以下参考资料:

@ruan-cat/vercel-deploy-tool 自有部署工具没有考虑到边缘计算函数的情况

我的项目普遍会包含至少一个主项目,一个文档项目,并且很多项目的仓库并不在 github 内,无法在 cloudflare 或 vercel 云平台内触发部署。故必须使用自己封装的库来完成部署。

本工具之前设计时,仅仅是为了准备上传静态文件。即使用 vc build 命令的特点,为项目准备好 .vercel/output/static 文件夹,随后上传到 vercel 平台。

上述方案是要求我们准备好云函数的文件结构目录的,云函数目录要求满足 .vercel/output/functions/index.func 结构,目前我的工具没办法实现这个目录结构,而且识别与处理都很麻烦。

因此,我需要新的方式准备好云函数的文件目录。

使用 vite-plugin-vercel 插件生成云函数目录结构

很幸运能够找到这个插件,这个插件可以让 vite 项目的内容,生成出Vercel Output API (v3)规范的目录结构。包括云函数。这就解决了上面的问题。

安装依赖 http-proxy-middleware

bash
pnpm i -P http-proxy-middleware

我们要在产物内准备好能够被 vercel 平台识别的云函数,这个云函数是生产就绪的,所以要安装成生产环境依赖。先按照教程要求,准备好该代理工具。

新建云函数

按照 vite-plugin-vercel 和上面参考资料的要求,在 vite 项目根目录内,新建 _api\proxy.js 云函数。

代码如下:

_api\proxy.js 云函数
js
import { createProxyMiddleware } from "http-proxy-middleware";

/** @see https://yalisky.eu.org/blogs/2023/12/28/vercel配置跨域 */
export default async function handler(req, res) {
	// 判断请求路径是否以 '/backend' 开头,设置代理目标
	const target = req.url.startsWith("/backend") ? "被代理的接口baseUrl" : "";

	console.log(" 在边缘请求内:req.url ", req.url);

	if (target) {
		// 设置 CORS 头
		res.setHeader("Access-Control-Allow-Origin", "*");
		res.setHeader("Access-Control-Allow-Methods", "GET,HEAD,PUT,PATCH,POST,DELETE");
		res.setHeader("Access-Control-Allow-Headers", "Content-Type");

		// 创建代理并等待完成
		await new Promise((resolve) => {
			createProxyMiddleware({
				target,
				changeOrigin: true,
				pathRewrite: {
					"^/backend/": "/",
				},
			})(req, res, resolve);
		});
	} else {
		// 如果没有找到匹配的路径,返回 404
		res.statusCode = 404;
		res.end("Not Found");
	}
}

云函数必须写在 _api 目录内

按照文档要求,为了避免重复构建和意外行为,需要将云函数写在 _api 目录内。

文档明确要求

2025-06-15-17-26-56

目前能诱发出来的意外情况是,http-proxy-middleware 在服务器内找不到,本地因为重复构建,导致依赖丢失。

http-proxy-middleware 找不到

2025-06-15-17-33-23

在 vite.config.ts 内使用 vite-plugin-vercel 插件

使用插件
ts
import { defineConfig } from "vite";
import vercel from "vite-plugin-vercel";

export default defineConfig(({ mode }) => {
	return {
		plugins: [vercel()],
	};
});

匹配接口路径到云函数

我们需要让满足特定前缀的后端接口,被代理到我们自写的代理中间件内。

如果我使用的是 vercel 平台的部署,那么在项目根目录内的 vercel.json 写以下内容即可。假设接口的反向代理前缀为: /backend

json
{
	"rewrites": [
		{
			"source": "/backend/(.*)",
			"destination": "/api/proxy"
		}
	]
}

一般情况下,做到这一步,就可以了。但是我的情况需要使用 Vercel Output API (v3)完成部署,没办法在被部署的产物内写入上述的配置。

只能稍微变通一下,在 vite-plugin-vercel 插件提供的 vercel 配置内,补全上述配置。

在 vite 内补全 vercel.json 配置
ts
import { defineConfig } from "vite";
export default defineConfig(({ mode }) => {
	return {
		/** @see https://github.com/magne4000/vite-plugin-vercel/tree/v9 */
		vercel: {
			rewrites: [
				// https://segmentfault.com/a/1190000042276351
				{ source: "/backend/(.*)", destination: "/api/proxy" },
			],
		},
	};
});

这样,vercel.json 的配置就能直接写入到本地的 .vercel/output 目录内,进而完成反向代理。

前端项目仍旧需要完成 vite 的反向代理配置

上述文章仅仅是说明在 vercel 平台内,给接口配置反向代理。项目本身也是需要配置 vite 的前端反向代理的。

贡献者

The avatar of contributor named as ruan-cat ruan-cat

页面历史

布局切换

调整 VitePress 的布局样式,以适配不同的阅读习惯和屏幕环境。

全部展开
使侧边栏和内容区域占据整个屏幕的全部宽度。
全部展开,但侧边栏宽度可调
侧边栏宽度可调,但内容区域宽度不变,调整后的侧边栏将可以占据整个屏幕的最大宽度。
全部展开,且侧边栏和内容区域宽度均可调
侧边栏宽度可调,但内容区域宽度不变,调整后的侧边栏将可以占据整个屏幕的最大宽度。
原始宽度
原始的 VitePress 默认布局宽度

页面最大宽度

调整 VitePress 布局中页面的宽度,以适配不同的阅读习惯和屏幕环境。

调整页面最大宽度
一个可调整的滑块,用于选择和自定义页面最大宽度。

内容最大宽度

调整 VitePress 布局中内容区域的宽度,以适配不同的阅读习惯和屏幕环境。

调整内容最大宽度
一个可调整的滑块,用于选择和自定义内容最大宽度。

聚光灯

支持在正文中高亮当前鼠标悬停的行和元素,以优化阅读和专注困难的用户的阅读体验。

ON开启
开启聚光灯。
OFF关闭
关闭聚光灯。