Firebase Admin SDK在Node.js(Heroku)中无法读写无报错,求正确实现方案
Let's break down exactly what's going wrong here and how to fix it step by step:
Why Your Current Setup Isn't Working
When you use admin.credential.applicationDefault(), the SDK looks for credentials in a few places—usually a local service account JSON file or the GOOGLE_APPLICATION_CREDENTIALS environment variable. On Heroku, though:
- You can't reliably keep a local JSON file (dynos are ephemeral and reset daily)
- Setting
GOOGLE_APPLICATION_CREDENTIALSonly for the current session doesn't persist across dyno restarts - Worst of all, if the SDK can't find valid credentials, it often fails silently (especially if you aren't properly handling Promise results), which explains why your writes do nothing and throw no errors.
Securely Deploy Your Service Account Key (No GitHub Exposure)
Here's how to get your service account key onto Heroku without committing it to version control:
- Download your service account JSON: Go to your Firebase Console → Project Settings → Service Accounts → "Generate New Private Key". Save this file locally (don't commit it to GitHub—add it to
.gitignoreif you haven't already). - Encode the JSON to Base64: Open your terminal, navigate to where you saved the JSON file, and run:
This converts the entire JSON into a single string, avoiding escape character headaches.cat your-service-account-file.json | base64 - Add the Base64 string as a Heroku environment variable:
- Go to your Heroku app dashboard → Settings → "Config Vars"
- Add a new variable named
FIREBASE_SERVICE_ACCOUNTand paste the Base64 string as its value.
Update Your Firebase Admin Initialization Code
Replace your current initialization code with this, which pulls the credential from the environment variable:
const admin = require('firebase-admin'); // Decode the Base64 service account string back into JSON const serviceAccount = JSON.parse( Buffer.from(process.env.FIREBASE_SERVICE_ACCOUNT, 'base64').toString() ); // Initialize the Admin SDK with the decoded credential admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: "https://<APP>.firebaseio.com" // Keep your actual app URL here }); const database = admin.database();
This setup will work reliably even after Heroku dyno restarts, since environment variables persist across restarts.
Fix the "No Response/No Errors" Problem
The reason you're not seeing any feedback is that you aren't properly handling the Promise returned by Firebase operations. Always attach .then() and .catch() handlers (or use async/await) and log results/errors to debug:
Option 1: Using Async/Await (Cleaner for sequential code)
async function testFirebaseWrite() { try { await database.ref("test").set("Hello World!"); console.log("✅ Successfully wrote to Firebase!"); } catch (error) { console.error("❌ Firebase write failed:", error); } } // Call the test function testFirebaseWrite();
Option 2: Using Promise Chaining
database.ref("test").set("Hello World!") .then(() => console.log("✅ Firebase write succeeded!")) .catch((error) => console.error("❌ Firebase write failed:", error));
Now you'll see clear logs in your Heroku dyno (run heroku logs --tail in your terminal to watch live logs) if something goes wrong—like invalid credentials or database permissions.
Verify Your Setup
To make sure the environment variable is loading correctly, add this line right after initializing the SDK:
console.log("Firebase service account loaded:", !!process.env.FIREBASE_SERVICE_ACCOUNT);
If you see Firebase service account loaded: true in your Heroku logs, the credential is being pulled in correctly.
内容的提问来源于stack exchange,提问作者simplexshotz

