Firebase Functions部署Next.js应用出现304、403及CORS错误
问题根因
你碰到的403、跳转Google登录、连带的CORS报错都不是CORS配置导致的,核心是三个配置错误:
firebase.json里配置的public: "out"是Next.js静态导出模式才会生成的目录,SSR构建不会产出这个目录,Firebase Hosting匹配不到public目录下的资源时会直接返回403,根本不会触发rewrite规则把请求转发给云函数- 云函数运行时工作目录和你本地开发的根目录不一致,当前Next.js初始化逻辑找不到
.next构建产物,触发Google Cloud默认的权限拦截,才会把请求重定向到Google账号登录页,所谓的CORS报错只是重定向后的连锁反应——登录页当然不会给你的自定义域名返回跨域允许头 - 你把所有路径全量转发给云函数,没有让CDN优先处理静态资源,所有JS、CSS、图片请求全打到云函数,既触发权限问题,还会导致页面加载极慢、冷启动时间超长
修复步骤
1. 调整目录结构
不要把functions的source设为项目根目录,按Firebase约定调整:
- 项目根目录存放
firebase.json、.firebaserc、Next.js源码、package.json、next.config.js、pages目录等 - 根目录新建
functions文件夹,把原有的server.js移入该文件夹,在functions目录下执行npm i firebase-functions next react react-dom安装云函数运行需要的依赖 - 根目录执行
next build生成.next构建产物,构建完成后把整个.next文件夹复制到functions目录下,避免云函数运行时找不到构建文件
2. 修正云函数入口代码
不要把app.prepare()放到每个请求的回调里执行,冷启动阶段一次性初始化即可,同时指定正确的构建文件绝对路径,functions/server.js替换为以下内容:
const { https } = require("firebase-functions"); const { default: next } = require("next"); const path = require("path"); const dev = process.env.NODE_ENV !== "production"; const app = next({ dev, conf: { distDir: path.join(__dirname, ".next") }, }); const handle = app.getRequestHandler(); // 冷启动阶段一次性完成Next.js初始化 const nextReady = app.prepare(); exports.nextSsrServer = https.onRequest(async (req, res) => { await nextReady; return handle(req, res); });
额外权限检查:去GCP控制台的IAM页面,找到云函数运行时服务账号(格式为
<你的项目ID>@appspot.gserviceaccount.com),给它绑定Storage Object Viewer角色,避免运行时读文件触发权限拦截。
3. 修正firebase.json配置
去掉错误的out公共目录配置,静态资源优先交给Hosting CDN处理,仅SSR路由转发给云函数,配置替换为:
{ "hosting": { "public": "public", "ignore": ["firebase.json", "**/.*", "**/node_modules/**"], "rewrites": [ { "source": "!{_next/**,images/**,*.js,*.css,*.png,*.jpg,*.webp,*.webmanifest,*.ico}", "function": "nextSsrServer" } ], "headers": [ { "source": "_next/**", "headers": [ { "key": "Cache-Control", "value": "public, max-age=31536000, immutable" } ] } ] }, "functions": { "source": "functions" } }
- 根目录新建空的
public文件夹,把functions/.next/static整个目录复制到public/_next下,项目里的images静态资源目录也复制到public目录下,这些资源会直接由CDN分发,不会再请求到云函数。
4. 重新部署
按顺序执行命令部署即可:
# 构建Next.js生产产物 npm run build # 复制静态资源到对应目录 cp -r .next functions/ mkdir -p public/_next cp -r .next/static public/_next/ cp -r images public/ # 部署云函数和Hosting firebase deploy --only functions,hosting
部署完成后所有资源都会正常返回200,不需要额外写任何CORS相关配置,之前的连锁报错会全部消失。
内容的提问来源于stack exchange,提问作者O. K.
相关产品推荐
相关产品推荐

