Skip to main content
Version: 1.0.0

Useful Commands and Best Practices

Most Common Firebase-Tools Commands

1. Functions Deployment

# Deploy all functions
firebase deploy --only functions

# Deploy a specific function
firebase deploy --only functions:functionName

# Deploy with security check
firebase deploy --only functions --force

2. Logs Visualisation

# View logs in real-time
firebase functions:log

# Logs for a specific function
firebase functions:log --only functionName

# Logs with time filter
firebase functions:log --since 2h

3. Emulators for Local Development

# Start all emulators
firebase emulators:start

# Start only functions emulator
firebase emulators:start --only functions

# Start with custom port
firebase emulators:start --only functions --functions-port 5001

4. Other Useful Commands

# Login/logout
firebase login
firebase logout

# Project initialisation
firebase init functions

# List projects
firebase projects:list

# Switch active project
firebase use project-id

Best Practices for Firebase Functions

1. Project Structure

functions/
├── lib/ # Main folder for functions
│ ├── processPdData.js # Classic Firebase functions
│ ├── verifyAndCreateToken.js # Classic Firebase functions
│ ├── sendMail.js # Classic Firebase functions
│ ├── getLocationFromIP.js # Classic Firebase functions
│ ├── notifications/ # Subfolder for notification functions
│ │ ├── supportRequests.js
│ │ ├── weeklySkuAssigned.js
│ │ ├── licenseHasExpired.js
│ │ └── quotationRequest.js
│ └── service/ # Configuration/service files
│ ├── staging-firebase-adminsdk.json # Staging service account
│ └── production-firebase-adminsdk.json # Production service account
└── index.js # Main export file

Example of file in lib/ folder

// lib/notifications/supportRequests.js
const { onRequest } = require("firebase-functions/v2/https");
const { db } = require("../config/firebase");

exports.processSupportRequest = onRequest(async (req, res) => {
// CORS configuration
res.set("Access-Control-Allow-Origin", "*");
res.set("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
res.set("Access-Control-Allow-Headers", "Content-Type, Authorization");

// Handle preflight OPTIONS request
if (req.method === "OPTIONS") {
return res.status(204).send("");
}

try {
// Verify it's a POST request
if (req.method !== "POST") {
return res.status(405).json({ error: "Method not allowed. Use POST." });
}

const { supportRequestId } = req.body;

if (!supportRequestId) {
return res.status(400).json({ error: "Support request ID required." });
}

// Function logic
const supportRequestRef = db
.collection("SupportRequests")
.doc(supportRequestId);
const supportRequestDoc = await supportRequestRef.get();

if (!supportRequestDoc.exists) {
return res.status(404).json({ error: "Support request not found." });
}

// Process the request...
const result = await processRequest(supportRequestDoc.data());

res.status(200).json({
success: true,
message: "Request processed successfully",
data: result,
});
} catch (error) {
console.error("Error processing support request:", error);
res.status(500).json({
error: "Internal server error",
details: error.message,
});
}
});

2. Export in index.js file

// index.js - Simple export example

// Import classic functions from lib/ folder
const { processPdData } = require("./lib/processPdData");
const { verifyAndCreateToken } = require("./lib/verifyAndCreateToken");
const { sendMail } = require("./lib/sendMail");

// Import notification functions from lib/notifications/ subfolder
const {
processSupportRequest,
} = require("./lib/notifications/supportRequests");

// Export to make them available as Firebase Functions
exports.processPdData = processPdData;
exports.verifyAndCreateToken = verifyAndCreateToken;
exports.sendMail = sendMail;
exports.processSupportRequest = processSupportRequest;

3. Best Practices for Performance

Global Initialisation

// ✅ Good: global initialisation
const admin = require("firebase-admin");
admin.initializeApp();

exports.myFunction = functions.https.onRequest((req, res) => {
// Admin connection is already ready
});

Cold Start Management

// ✅ Minimise dependencies
const functions = require("firebase-functions");

// ✅ Use lazy loading for heavy modules
exports.heavyFunction = functions.https.onRequest(async (req, res) => {
const heavyModule = require("./heavy-module"); // Load only when necessary
});

4. Best Practices for Security

Input Validation

exports.secureFunction = functions.https.onRequest((req, res) => {
// ✅ Always validate input
if (!req.body.userId || typeof req.body.userId !== "string") {
return res.status(400).json({ error: "Invalid userId" });
}

// ✅ Sanitise data
const userId = req.body.userId.trim();
});

Authentication

exports.authenticatedFunction = functions.https.onRequest(async (req, res) => {
try {
// ✅ Verify JWT token
const token = req.headers.authorization?.replace("Bearer ", "");
const decodedToken = await admin.auth().verifyIdToken(token);

// Proceed with function logic
} catch (error) {
return res.status(401).json({ error: "Unauthorised" });
}
});

5. Best Practices for Maintainability

CamelCase Nomenclature

// ✅ Use camelCase for function and variable names
exports.getUserProfile = functions.https.onRequest((req, res) => {
const userEmail = req.body.email;
const isValidEmail = validateEmail(userEmail);
});

Error Handling

exports.robustFunction = functions.https.onRequest(async (req, res) => {
try {
// Main logic
const result = await performOperation();
res.json({ success: true, data: result });
} catch (error) {
// ✅ Detailed logging for debugging
console.error("Error in robustFunction:", error);

// ✅ User-friendly response
res.status(500).json({
error: "Internal server error",
timestamp: new Date().toISOString(),
});
}
});

Timeout and Resource Management

// ✅ Set appropriate timeouts
exports.longRunningFunction = functions
.runWith({ timeoutSeconds: 300, memory: "1GB" })
.https.onRequest(async (req, res) => {
// Operations requiring more time/memory
});

6. Monitoring and Debugging

// ✅ Use structured logging
const { logger } = require("firebase-functions");

exports.monitoredFunction = functions.https.onRequest((req, res) => {
logger.info("Function started", {
userId: req.body.userId,
timestamp: Date.now(),
});

try {
// Function logic
logger.info("Operation completed successfully");
} catch (error) {
logger.error("Operation failed", { error: error.message });
}
});