Next.js接入Firebase后本地正常 部署Vercel返回500错误如何解决
Next.js + Firestore API路由部署到Vercel返回500错误
大家好,我当前遇到了棘手的开发问题:
我正在Next.js应用的API模块中使用Firebase,本地开发环境、本地构建的生产版本运行均正常,但部署到Vercel生产环境后会返回500 - Internal Server Error。经排查已定位到错误是由await getDocs(q)调用触发,但暂未找到修复方案。
我的核心需求是基于Firestore的数据实现动态API路由,相关代码如下:
firebase.js
// Import the functions you need from the SDKs you need import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore"; import { getStorage } from "firebase/storage"; // TODO: Add SDKs for Firebase products that you want to use // https://firebase.google.com/docs/web/setup#available-libraries // Your web app's Firebase configuration // For Firebase JS SDK v7.20.0 and later, measurementId is optional const firebaseConfig = { apiKey: "<REDACTED_FOR_STACKOVERFLOW>", authDomain: "<REDACTED_FOR_STACKOVERFLOW>", databaseURL: "<REDACTED_FOR_STACKOVERFLOW>", projectId: "<REDACTED_FOR_STACKOVERFLOW>", storageBucket: "<REDACTED_FOR_STACKOVERFLOW>", messagingSenderId: "<REDACTED_FOR_STACKOVERFLOW>", appId: "<REDACTED_FOR_STACKOVERFLOW>", measurementId: "<REDACTED_FOR_STACKOVERFLOW>" }; // Initialize Firebase const app = initializeApp(firebaseConfig); // Database const db = getFirestore(); // Storage const storage = getStorage(app) export { app, storage, db }
/api/users/[name].js
import { db } from './firebase.js' export default async function handler(req, res) { try { const { name } = req.query let users = [] const q = query(collection(db, "users"), where("name", "==", name)) const querySnapshot = await getDocs(q) if (querySnapshot.empty) { res.status(404).json({error: "Document does not exist."}) } else { querySnapshot.forEach((doc) => { users.push(doc.data()) }) res.status(200).json(users) } } catch(err) { res.status(404).json({error: err}) } }
package.json
{ "name": "app-frontend", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@headlessui/react": "^1.4.2", "@heroicons/react": "^1.0.5", "bootstrap": "^4.6.0", "classnames": "^2.2.6", "next": "11.0.1", "firebase": "^9.5.0", "postcss-custom-properties": "^8.0.11", "postcss-flexbugs-fixes": "^5.0.2", "postcss-import": "^14.0.2", "postcss-nested": "^5.0.5", "postcss-nesting": "^8.0.1", "postcss-preset-env": "^6.7.0", "react": "17.0.2", "react-dom": "17.0.2", "react-icons": "^4.2.0", "react-markdown": "^6.0.2", "react-pro-sidebar": "^0.6.0", "react-remark": "^2.0.3", "rehype-raw": "^5.1.0", "rehype-react": "^6.2.1", "remark-html": "^13.0.1", "remark-react": "^8.0.0", "remark-rehype": "^8.1.0", "sass": "^1.35.1", "xhr2": "^0.2.1" }, "devDependencies": { "autoprefixer": "^10.2.6", "eslint": "7.29.0", "eslint-config-next": "11.0.1", "postcss": "^8.3.5", "tailwindcss": "^2.2.4" } }
服务端返回的错误开头如下:
@firebase/firestore: Firestore (9.5.0): INTERNAL UNHANDLED ERROR: Error: ENOENT: no such file or directory, open '/var/task/node_modules/@firebase/firestore/dist/src/protos/google/firestore/v1/firestore.proto'
恳请各位帮忙提供解决方案,谢谢。
解决方案
这个错误的根本原因是Vercel部署Next.js应用时,Serverless Function的依赖追踪逻辑会默认剔除它认为不需要的非JS资源文件,导致Firestore依赖的proto协议文件没有被打包到部署包中,运行时读取失败。按照以下步骤操作即可修复:
- 补全API路由的方法导入
当前的/api/users/[name].js中没有导入query、collection、where、getDocs这几个Firestore方法,本地未开启严格tree shaking时可以正常运行,生产环境会触发未定义错误。在文件顶部添加导入:
import { collection, query, where, getDocs } from "firebase/firestore";
- 修正Firestore初始化逻辑
firebase.js中初始化Firestore时需要传入已初始化的app实例,修改代码:
// 原代码 const db = getFirestore(); const db = getFirestore(app);
- 配置Next.js打包规则,强制包含proto文件
在项目根目录的next.config.js中添加如下配置,让构建时把Firestore依赖的proto文件打包到部署包中:
module.exports = { experimental: { outputFileTracingIncludes: { '/api/**/*': ['./node_modules/@firebase/firestore/dist/src/protos/**/*'], }, }, // 保留你原有其他配置 }
如果需要更稳定的服务端Firestore调用体验,也可以直接改用Firebase Admin SDK实现API路由逻辑,Admin SDK专为服务端环境设计,不会出现这类客户端SDK的打包兼容问题。
内容的提问来源于stack exchange,提问作者Mario Lopez
相关产品推荐
相关产品推荐

