当一个 Vue 3 项目逐渐成型,总会遇到一些纯前端搞不定的事情:需要保密的第三方 API 密钥、需要服务端参与的登录鉴权、需要写数据库的业务逻辑。传统做法是再开一个 Node.js 后端项目,但如果你不想买服务器、不想管运维,Google Cloud Functions 提供了一个更轻量的选择。它是一种无服务器计算服务,你只需要写一个个函数,部署上去就能被 HTTP 请求触发,按调用次数和执行时长计费,不用的时候不产生费用。这篇文章就把 Vue 3 和 Cloud Functions 串起来,讲清楚从本地开发到线上部署的完整工程化流程。

一、先搞清楚 Cloud Functions 的运行机制
Cloud Functions 是事件驱动的计算模型,目前主流版本是第二代(Cloud Run functions),底层跑在 Cloud Run 和 Eventarc 上。对前端开发者来说,最常用的触发方式是 HTTP 触发:部署完成后,谷歌会给你一个形如 https://region-project.cloudfunctions.net/function-name 的公开 URL,任何 fetch 或 axios 请求都能直接调用它。
第二代函数支持并发处理,单个实例可以同时处理多个请求,这一点对冷启动优化非常关键。第一代函数每个实例同一时刻只能处理一个请求,流量突增时谷歌会不断扩容新实例,冷启动次数明显更多。而第二代函数在实例预热后可以复用,配合最小实例数配置,可以把响应延迟从秒级压到毫秒级。
还需要理解冷启动这个概念。函数不是常驻进程,一段时间没有请求后实例会被回收,下次请求到来时需要重新加载运行时和你的代码,这个过程就是冷启动。对于 Node.js 运行时来说,如果代码里 require 了大量依赖,冷启动时间会明显变长。所以写函数时要尽量精简依赖,把数据库连接池等重量级对象放到模块顶层,这样实例复用时可以直接使用:
// functions/src/auth.js
const { Firestore } = require('@google-cloud/firestore');
// 放在模块顶层,实例复用时不会重复初始化
const db = new Firestore();
exports.handler = async (req, res) => {
// 每个请求直接复用 db 实例,避免冷启动后的重复建连开销
const users = await db.collection('users').limit(10).get();
res.json(users.docs.map(d => d.data()));
};二、本地开发环境搭建与项目结构设计
工程化的第一步是设计合理的项目结构。我推荐采用 Monorepo 风格,把前端和函数放在同一个仓库里,这样类型定义、公共工具函数都能共享,改一处代码两边的联动一目了然:
my-project/ ├── web/ # Vue 3 前端项目(Vite) │ ├── src/ │ │ ├── api/ # 封装云端函数调用的统一层 │ │ └── ... │ └── vite.config.js ├── functions/ # 云端函数集合 │ ├── src/ │ │ ├── auth.js │ │ ├── order.js │ │ └── index.js # 函数入口注册 │ └── package.json └── package.json # 根目录脚本,统一管理命令
本地调试不需要真的部署到谷歌云,官方提供了 @google-cloud/functions-framework,它可以在本地启动一个模拟 HTTP 服务的进程。在 functions 目录安装依赖后,执行 npx functions-framework --target=auth --port=8081,本地就有一个和线上行为几乎一致的函数服务。
接着要解决跨域问题。本地运行时 Vue 项目跑在 Vite 的 5173 端口,函数跑在 8081 端口,浏览器直接请求会被同源策略拦截。最优雅的做法是配置 Vite 代理,让请求看起来是同源的:
// web/vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
proxy: {
// 前端请求 /api 开头的路径时,转发到本地函数服务
'/api': {
target: 'http://127.0.0.1:8081',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
}
})线上环境则建议在函数侧配置 CORS 响应头,或者更省事的方案是在谷歌云上配一个 API Gateway 做统一入口。开发阶段用代理、生产阶段用同域网关,是这类项目最常见组合。
三、前端调用层的统一封装
不要在 Vue 组件里散落各处的 fetch 调用,工程化的关键是在 web/src/api 下建一个统一调用层。它负责拼 URL、注入凭证、统一错误处理,组件只关心业务数据:
// web/src/api/client.js
import { useUserStore } from '@/stores/user'
const BASE = import.meta.env.DEV ? '/api' : 'https://asia-east2-my-project.cloudfunctions.net'
export async function callFunction(name, payload = {}) {
const userStore = useUserStore()
const res = await fetch(`${BASE}/${name}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: userStore.token ? `Bearer ${userStore.token}` : ''
},
body: JSON.stringify(payload)
})
if (!res.ok) {
const err = await res.json().catch(() => ({}))
throw new Error(err.message || `函数 ${name} 调用失败`)
}
return res.json()
}封装好之后,业务代码变得非常干净。比如一个提交订单的组件里,只需要 const result = await callFunction('createOrder', { items }) 一行就能拿到结果。Token 过期、权限不足等通用逻辑都可以在 client 这一层做拦截处理,避免每个页面重复写判断逻辑。
另外建议给每个函数的入参和返回值定义 JSDoc 类型或者直接用 TypeScript,这样前后端共享类型定义,函数改名或参数变更时编辑器能立刻提示,能省掉不少联调时间。
四、部署流程与环境变量管理
部署单个函数用 gcloud 命令行即可完成。先安装 Google Cloud CLI 并登录,然后执行:
gcloud functions deploy auth \ --gen2 \ --runtime=nodejs20 \ --region=asia-east2 \ --source=functions \ --entry-point=handler \ --trigger-http \ --allow-unauthenticated
环境变量不要硬编码在代码里。谷歌提供了 Secret Manager,把数据库密码、第三方密钥存进去,部署时通过 --set-secrets 参数注入,函数运行时用 process.env 读取即可,密钥不会出现在代码仓库里:
gcloud functions deploy auth \ --gen2 --runtime=nodejs20 --region=asia-east2 \ --source=functions --entry-point=handler --trigger-http \ --set-secrets=DB_PASSWORD=my-db-password:latest
最后是 CI/CD 自动化。在 GitHub Actions 里配一个工作流,监听主分支的变动,自动执行部署命令,再配合前端构建产物上传到 Firebase Hosting 或 Cloud Storage,一次 push 就能完成前后端的同步发布。整个流水线跑通之后,你的 Vue 3 项目就拥有了一个不需要自己维护服务器的完整后端能力,团队规模小也能快速迭代产品。
总结一下核心要点:理解冷启动并优化依赖加载、用 Monorepo 管理前后端代码、本地用 Functions Framework 加 Vite 代理调试、线上统一封装调用层、用 Secret Manager 管密钥并配好 CI/CD。把这些环节串起来,无服务器架构的工程化就不再是概念,而是每天都能顺手使用的生产力工具。
Vue 3Google Cloud Functions无服务器架构修改时间:2026-09-16 06:39:34