Firestore/Firebase无法使用Next.js



嘿,你们在这里真的很挣扎。

我正在尝试在我的Next.js应用程序中使用firebase,特别是针对api。当我在本地建立生产和本地开发时,它运行良好。但一旦我在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'

将firebase降级到9.4.0为我解决了确切的问题。我不确定这是否是一个好的解决方案,但它有效。

问题是,依赖项以某种方式安装在本地包node_modules中,但没有在package.json上定义。

你需要在package.json上定义它,这样它就会安装在构建阶段上

在项目文件夹上,打开终端并安装它,这样它就会被添加到包中:

npm install --save firebase

为此,如果您在getServerSideProps中使用handler函数或在index.js中使用其他函数,请尝试使用以下代码:

const q = query(collection(getFirestore(app), "users"), where("name", "==", name))

这对我有用。谢谢

我有一段时间面临同样的问题。问题是您使用的方法是在客户端初始化应用程序。

对于nodejs或基于服务器的初始化,请执行以下操作:

  • 转到firebase控制台,然后在项目设置中>服务帐户,导出一个新密钥(导出一个json文件,您应该位于项目的根目录中(

  • 然后创建utils/db.js,并在内部导入json文件并初始化应用程序:

import serviceAccount from "./file.json";
if (!admin.apps.length) {
try {
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
} catch (error) {
console.log("Firebase admin initialization error", error.stack);
}
}
export default admin.firestore();

瓦拉。如果同时使用SSR和CSR,请保留客户端和服务器端firebase连接的两种方法。

然后在你的页面/api/writever.js 中

import db from "/utils/db.js";
export default async function handler(req, res) {
try {
const entries = await db.collection("collection").get();
const entriesData = entries.docs.map((entry) => ({
id: entry.id,
...entry.data(),
}));
res.status(200).json({ entriesData });
} catch (e) {
res.status(400).end();
}
}

通过调用localhost:3000/api/athing 进行测试

最新更新