Zum Inhalt

Google's Backend-as-a-Service Platform

generieren

Firebase steht für Googles umfassende Backend-as-a-Service-Plattform (BaaS) wurde entwickelt, um die Anwendungsentwicklung zu beschleunigen, indem eine Suite mit Cloud-basierten Tools und Services bereitgestellt wird. Ursprünglich von Firebase Inc. entwickelt und von Google im Jahr 2014 erworben, hat sich Firebase zu einer kompletten Entwicklungsplattform entwickelt, die Backend-Infrastruktur, Echtzeit-Datensynchronisation, Authentifizierung, Hosting, Analytik und vieles mehr behandelt. Firebase bietet zwei primäre Datenbanklösungen: die ursprüngliche Realtime-Datenbank und die fortschrittlichere Cloud Firestore, die beide für Echtzeitanwendungen mit Offline-Funktionen und nahtloser Synchronisation über mehrere Clients konzipiert sind.

Erste Schritte mit Firebase

Projektaufbau und Konfiguration

```javascript // Install Firebase CLI npm install -g firebase-tools

// Login to Firebase firebase login

// Initialize Firebase project firebase init

// Install Firebase SDK for web npm install firebase

// Initialize Firebase in your application import \\{ initializeApp \\} from 'firebase/app'; import \\{ getFirestore \\} from 'firebase/firestore'; import \\{ getAuth \\} from 'firebase/auth'; import \\{ getStorage \\} from 'firebase/storage';

const firebaseConfig = \\{ apiKey: "your-api-key", authDomain: "your-project.firebaseapp.com", databaseURL: "https://your-project-default-rtdb.firebaseio.com", projectId: "your-project-id", storageBucket: "your-project.appspot.com", messagingSenderId: "123456789", appId: "your-app-id" \\};

// Initialize Firebase const app = initializeApp(firebaseConfig);

// Initialize services const db = getFirestore(app); const auth = getAuth(app); const storage = getStorage(app);

export \\{ db, auth, storage \\}; ```_

Firebase Console und Projektmanagement

```javascript // Firebase project structure // - Authentication: User management and sign-in // - Firestore Database: NoSQL document database // - Realtime Database: JSON tree database // - Storage: File storage service // - Hosting: Web hosting service // - Functions: Serverless functions // - Analytics: App usage analytics // - Performance: App performance monitoring

// Environment configuration // Development const devConfig = \\{ apiKey: "dev-api-key", authDomain: "dev-project.firebaseapp.com", projectId: "dev-project-id" \\};

// Production const prodConfig = \\{ apiKey: "prod-api-key", authDomain: "prod-project.firebaseapp.com", projectId: "prod-project-id" \\};

const config = process.env.NODE_ENV === 'production' ? prodConfig : devConfig; const app = initializeApp(config); ```_

Cloud Firestore (empfohlen)

Datenbankstruktur und Sammlungen

```javascript // Firestore data model: Collections -> Documents -> Fields // Collections contain documents // Documents contain fields and subcollections // Documents are identified by unique IDs

import \\{ collection, doc, addDoc, setDoc, getDoc, getDocs, updateDoc, deleteDoc, query, where, orderBy, limit, onSnapshot \\} from 'firebase/firestore';

// Reference to a collection const usersRef = collection(db, 'users');

// Reference to a specific document const userRef = doc(db, 'users', 'user123');

// Reference to a subcollection const postsRef = collection(db, 'users', 'user123', 'posts');

// Create document with auto-generated ID const createUser = async (userData) => \\{ try \\{ const docRef = await addDoc(collection(db, 'users'), \\{ name: userData.name, email: userData.email, createdAt: new Date(), isActive: true, profile: \\{ | bio: userData.bio | | '', | | avatar: userData.avatar | | '', | preferences: \\{ theme: 'light', notifications: true \\} \\} \\}); console.log('Document written with ID: ', docRef.id); return docRef.id; \\} catch (error) \\{ console.error('Error adding document: ', error); throw error; \\} \\};

// Create document with custom ID const createUserWithId = async (userId, userData) => \\{ try \\{ await setDoc(doc(db, 'users', userId), \\{ name: userData.name, email: userData.email, createdAt: new Date(), isActive: true \\}); console.log('Document created with custom ID: ', userId); \\} catch (error) \\{ console.error('Error creating document: ', error); throw error; \\} \\}; ```_

AUSRÜSTUNG Operationen

```javascript // CREATE - Add documents const addPost = async (userId, postData) => \\{ try \\{ const postRef = await addDoc(collection(db, 'users', userId, 'posts'), \\{ title: postData.title, content: postData.content, | tags: postData.tags | | [], | publishedAt: new Date(), isPublished: false, likes: 0, comments: [] \\}); return postRef.id; \\} catch (error) \\{ console.error('Error adding post: ', error); throw error; \\} \\};

// READ - Get single document const getUser = async (userId) => \\{ try \\{ const docSnap = await getDoc(doc(db, 'users', userId));

if (docSnap.exists()) \\\\{
  return \\\\{ id: docSnap.id, ...docSnap.data() \\\\};
\\\\} else \\\\{
  console.log('No such document!');
  return null;
\\\\}

\\} catch (error) \\{ console.error('Error getting document: ', error); throw error; \\} \\};

// READ - Get multiple documents const getAllUsers = async () => \\{ try \\{ const querySnapshot = await getDocs(collection(db, 'users')); const users = [];

querySnapshot.forEach((doc) => \\\\{
  users.push(\\\\{ id: doc.id, ...doc.data() \\\\});
\\\\});

return users;

\\} catch (error) \\{ console.error('Error getting documents: ', error); throw error; \\} \\};

// UPDATE - Update document const updateUser = async (userId, updates) => \\{ try \\{ const userRef = doc(db, 'users', userId); await updateDoc(userRef, \\{ ...updates, updatedAt: new Date() \\}); console.log('Document updated successfully'); \\} catch (error) \\{ console.error('Error updating document: ', error); throw error; \\} \\};

// UPDATE - Update nested fields const updateUserProfile = async (userId, profileUpdates) => \\{ try \\{ const userRef = doc(db, 'users', userId); await updateDoc(userRef, \\{ 'profile.bio': profileUpdates.bio, 'profile.avatar': profileUpdates.avatar, 'profile.preferences.theme': profileUpdates.theme, updatedAt: new Date() \\}); \\} catch (error) \\{ console.error('Error updating profile: ', error); throw error; \\} \\};

// DELETE - Delete document const deleteUser = async (userId) => \\{ try \\{ await deleteDoc(doc(db, 'users', userId)); console.log('Document deleted successfully'); \\} catch (error) \\{ console.error('Error deleting document: ', error); throw error; \\} \\}; ```_

Abfrage und Filterung

```javascript import \\{ query, where, orderBy, limit, startAt, endAt, startAfter, endBefore \\} from 'firebase/firestore';

// Simple queries const getActiveUsers = async () => \\{ const q = query( collection(db, 'users'), where('isActive', '==', true) );

const querySnapshot = await getDocs(q); return querySnapshot.docs.map(doc => (\\{ id: doc.id, ...doc.data() \\})); \\};

// Compound queries const getRecentActivePosts = async () => \\{ const q = query( collection(db, 'posts'), where('isPublished', '==', true), where('publishedAt', '>', new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)), orderBy('publishedAt', 'desc'), limit(10) );

const querySnapshot = await getDocs(q); return querySnapshot.docs.map(doc => (\\{ id: doc.id, ...doc.data() \\})); \\};

// Array queries const getPostsByTags = async (tags) => \\{ const q = query( collection(db, 'posts'), where('tags', 'array-contains-any', tags) );

const querySnapshot = await getDocs(q); return querySnapshot.docs.map(doc => (\\{ id: doc.id, ...doc.data() \\})); \\};

// Range queries const getUsersByAgeRange = async (minAge, maxAge) => \\{ const q = query( collection(db, 'users'), where('age', '>=', minAge), where('age', '<=', maxAge), orderBy('age') );

const querySnapshot = await getDocs(q); return querySnapshot.docs.map(doc => (\\{ id: doc.id, ...doc.data() \\})); \\};

// Pagination const getPaginatedUsers = async (pageSize = 10, lastDoc = null) => \\{ let q = query( collection(db, 'users'), orderBy('createdAt', 'desc'), limit(pageSize) );

if (lastDoc) \\{ q = query( collection(db, 'users'), orderBy('createdAt', 'desc'), startAfter(lastDoc), limit(pageSize) ); \\}

const querySnapshot = await getDocs(q); const users = querySnapshot.docs.map(doc => (\\{ id: doc.id, ...doc.data() \\})); const lastVisible = querySnapshot.docs[querySnapshot.docs.length - 1];

return \\{ users, lastDoc: lastVisible, hasMore: users.length === pageSize \\}; \\};

// Text search (limited - consider Algolia for full-text search) const searchUsersByName = async (searchTerm) => \\{ const q = query( collection(db, 'users'), where('name', '>=', searchTerm), where('name', '<=', searchTerm + '\uf8ff'), orderBy('name'), limit(10) );

const querySnapshot = await getDocs(q); return querySnapshot.docs.map(doc => (\\{ id: doc.id, ...doc.data() \\})); \\}; ```_

Hörer in Echtzeit

```javascript // Real-time listener for single document const subscribeToUser = (userId, callback) => \\{ const userRef = doc(db, 'users', userId);

const unsubscribe = onSnapshot(userRef, (doc) => \\{ if (doc.exists()) \\{ callback(\\{ id: doc.id, ...doc.data() \\}); \\} else \\{ callback(null); \\} \\}, (error) => \\{ console.error('Error listening to user: ', error); \\});

return unsubscribe; // Call this function to stop listening \\};

// Real-time listener for collection const subscribeToActiveUsers = (callback) => \\{ const q = query( collection(db, 'users'), where('isActive', '==', true), orderBy('createdAt', 'desc') );

const unsubscribe = onSnapshot(q, (querySnapshot) => \\{ const users = []; querySnapshot.forEach((doc) => \\{ users.push(\\{ id: doc.id, ...doc.data() \\}); \\}); callback(users); \\}, (error) => \\{ console.error('Error listening to users: ', error); \\});

return unsubscribe; \\};

// Listen to document changes with metadata const subscribeToUserWithMetadata = (userId, callback) => \\{ const userRef = doc(db, 'users', userId);

const unsubscribe = onSnapshot(userRef, \\{ includeMetadataChanges: true \\}, (doc) => \\{ const source = doc.metadata.hasPendingWrites ? 'Local' : 'Server'; const data = doc.exists() ? \\{ id: doc.id, ...doc.data() \\} : null;

callback(\\\\{ data, source, fromCache: doc.metadata.fromCache \\\\});

\\});

return unsubscribe; \\};

// React hook example for real-time data const useUser = (userId) => \\{ const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null);

useEffect(() => \\{ if (!userId) \\{ setUser(null); setLoading(false); return; \\}

const unsubscribe = subscribeToUser(userId, (userData) => \\\\{
  setUser(userData);
  setLoading(false);
  setError(null);
\\\\});

return () => unsubscribe();

\\}, [userId]);

return \\{ user, loading, error \\}; \\}; ```_

Transaktionen und Batch-Operationen

```javascript import \\{ runTransaction, writeBatch, increment, arrayUnion, arrayRemove, serverTimestamp \\} from 'firebase/firestore';

// Transaction example - Transfer points between users const transferPoints = async (fromUserId, toUserId, points) => \\{ try \\{ await runTransaction(db, async (transaction) => \\{ const fromUserRef = doc(db, 'users', fromUserId); const toUserRef = doc(db, 'users', toUserId);

  const fromUserDoc = await transaction.get(fromUserRef);
  const toUserDoc = await transaction.get(toUserRef);

| if (!fromUserDoc.exists() | | !toUserDoc.exists()) \\{ | throw new Error('One or both users do not exist'); \\}

| const fromUserPoints = fromUserDoc.data().points | | 0; |

  if (fromUserPoints < points) \\\\{
    throw new Error('Insufficient points');
  \\\\}

  transaction.update(fromUserRef, \\\\{
    points: fromUserPoints - points,
    updatedAt: serverTimestamp()
  \\\\});

  transaction.update(toUserRef, \\\\{
    points: increment(points),
    updatedAt: serverTimestamp()
  \\\\});
\\\\});

console.log('Points transferred successfully');

\\} catch (error) \\{ console.error('Transaction failed: ', error); throw error; \\} \\};

// Batch operations const batchUpdateUsers = async (userUpdates) => \\{ const batch = writeBatch(db);

userUpdates.forEach((\\{ userId, updates \\}) => \\{ const userRef = doc(db, 'users', userId); batch.update(userRef, \\{ ...updates, updatedAt: serverTimestamp() \\}); \\});

try \\{ await batch.commit(); console.log('Batch update completed'); \\} catch (error) \\{ console.error('Batch update failed: ', error); throw error; \\} \\};

// Array operations const addTagToPost = async (postId, tag) => \\{ const postRef = doc(db, 'posts', postId); await updateDoc(postRef, \\{ tags: arrayUnion(tag), updatedAt: serverTimestamp() \\}); \\};

const removeTagFromPost = async (postId, tag) => \\{ const postRef = doc(db, 'posts', postId); await updateDoc(postRef, \\{ tags: arrayRemove(tag), updatedAt: serverTimestamp() \\}); \\};

// Increment/decrement operations const likePost = async (postId) => \\{ const postRef = doc(db, 'posts', postId); await updateDoc(postRef, \\{ likes: increment(1), updatedAt: serverTimestamp() \\}); \\}; ```_

Firebase Realtime Datenbank

Datenbankstruktur und Referenzen

```javascript import \\{ getDatabase, ref, set, get, push, update, remove, on, off, child, orderByChild, orderByKey, orderByValue, limitToFirst, limitToLast, startAt, endAt, equalTo \\} from 'firebase/database';

// Initialize Realtime Database const rtdb = getDatabase();

// Database structure (JSON tree) // \\{ // "users": \\{ // "user1": \\{ // "name": "John Doe", // "email": "john@example.com", // "posts": \\{ // "post1": true, // "post2": true // \\} // \\} // \\}, // "posts": \\{ // "post1": \\{ // "title": "First Post", // "content": "Hello World", // "author": "user1", // "timestamp": 1642694400000 // \\} // \\} // \\}

// Create references const usersRef = ref(rtdb, 'users'); const userRef = ref(rtdb, 'users/user1'); const postsRef = ref(rtdb, 'posts'); ```_

AUSRÜSTUNG Operationen in Echtzeit-Datenbank

``javascript // CREATE/UPDATE - Set data const createUser = async (userId, userData) => \\\\{ try \\\\{ await set(ref(rtdb,users/$\{userId\}`), \\{ name: userData.name, email: userData.email, createdAt: Date.now(), isActive: true \\}); console.log('User created successfully'); \\} catch (error) \\{ console.error('Error creating user: ', error); throw error; \\} \\};

// CREATE - Push data (auto-generated key) const addPost = async (postData) => \\{ try \\{ const newPostRef = push(ref(rtdb, 'posts')); await set(newPostRef, \\{ title: postData.title, content: postData.content, author: postData.author, timestamp: Date.now(), likes: 0 \\}); return newPostRef.key; \\} catch (error) \\{ console.error('Error adding post: ', error); throw error; \\} \\};

// READ - Get data once const getUser = async (userId) => \\{ try \\{ const snapshot = await get(ref(rtdb, users/$\\{userId\\})); if (snapshot.exists()) \\{ return \\{ id: userId, ...snapshot.val() \\}; \\} else \\{ console.log('No data available'); return null; \\} \\} catch (error) \\{ console.error('Error getting user: ', error); throw error; \\} \\};

// READ - Get all users const getAllUsers = async () => \\{ try \\{ const snapshot = await get(ref(rtdb, 'users')); if (snapshot.exists()) \\{ const users = []; snapshot.forEach((childSnapshot) => \\{ users.push(\\{ id: childSnapshot.key, ...childSnapshot.val() \\}); \\}); return users; \\} else \\{ return []; \\} \\} catch (error) \\{ console.error('Error getting users: ', error); throw error; \\} \\};

// UPDATE - Update specific fields const updateUser = async (userId, updates) => \\{ try \\{ await update(ref(rtdb, users/$\\{userId\\}), \\{ ...updates, updatedAt: Date.now() \\}); console.log('User updated successfully'); \\} catch (error) \\{ console.error('Error updating user: ', error); throw error; \\} \\};

// DELETE - Remove data const deleteUser = async (userId) => \\{ try \\{ await remove(ref(rtdb, users/$\\{userId\\})); console.log('User deleted successfully'); \\} catch (error) \\{ console.error('Error deleting user: ', error); throw error; \\} \\}; ```_

Echtzeit-Anhörer und Queries

``javascript // Real-time listener const subscribeToUser = (userId, callback) => \\\\{ const userRef = ref(rtdb,users/$\{userId\}`);

const unsubscribe = on(userRef, 'value', (snapshot) => \\{ const data = snapshot.exists() ? \\{ id: userId, ...snapshot.val() \\} : null; callback(data); \\}, (error) => \\{ console.error('Error listening to user: ', error); \\});

return () => off(userRef, 'value', unsubscribe); \\};

// Listen to child events const subscribeToUserPosts = (userId, callbacks) => \\{ const userPostsRef = ref(rtdb, users/$\\{userId\\}/posts);

const childAddedListener = on(userPostsRef, 'child_added', callbacks.onAdded); const childChangedListener = on(userPostsRef, 'child_changed', callbacks.onChanged); const childRemovedListener = on(userPostsRef, 'child_removed', callbacks.onRemoved);

return () => \\{ off(userPostsRef, 'child_added', childAddedListener); off(userPostsRef, 'child_changed', childChangedListener); off(userPostsRef, 'child_removed', childRemovedListener); \\}; \\};

// Queries with ordering and filtering const getTopPosts = async (limit = 10) => \\{ try \\{ const topPostsQuery = query( ref(rtdb, 'posts'), orderByChild('likes'), limitToLast(limit) );

const snapshot = await get(topPostsQuery);
const posts = [];

snapshot.forEach((childSnapshot) => \\\\{
  posts.unshift(\\\\{
    id: childSnapshot.key,
    ...childSnapshot.val()
  \\\\});
\\\\});

return posts;

\\} catch (error) \\{ console.error('Error getting top posts: ', error); throw error; \\} \\};

// Range queries const getPostsByDateRange = async (startDate, endDate) => \\{ try \\{ const dateRangeQuery = query( ref(rtdb, 'posts'), orderByChild('timestamp'), startAt(startDate), endAt(endDate) );

const snapshot = await get(dateRangeQuery);
const posts = [];

snapshot.forEach((childSnapshot) => \\\\{
  posts.push(\\\\{
    id: childSnapshot.key,
    ...childSnapshot.val()
  \\\\});
\\\\});

return posts;

\\} catch (error) \\{ console.error('Error getting posts by date range: ', error); throw error; \\} \\};

// Equal to query const getUsersByStatus = async (status) => \\{ try \\{ const statusQuery = query( ref(rtdb, 'users'), orderByChild('status'), equalTo(status) );

const snapshot = await get(statusQuery);
const users = [];

snapshot.forEach((childSnapshot) => \\\\{
  users.push(\\\\{
    id: childSnapshot.key,
    ...childSnapshot.val()
  \\\\});
\\\\});

return users;

\\} catch (error) \\{ console.error('Error getting users by status: ', error); throw error; \\} \\}; ```_

Firebase Authentication

Authentication Setup und Methoden

```javascript import \\{ getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, signInWithPopup, GoogleAuthProvider, FacebookAuthProvider, TwitterAuthProvider, signOut, onAuthStateChanged, updateProfile, updatePassword, sendPasswordResetEmail, deleteUser \\} from 'firebase/auth';

const auth = getAuth();

// Email/Password Authentication const signUpWithEmail = async (email, password, displayName) => \\{ try \\{ const userCredential = await createUserWithEmailAndPassword(auth, email, password); const user = userCredential.user;

// Update user profile
await updateProfile(user, \\\\{
  displayName: displayName
\\\\});

// Create user document in Firestore
await setDoc(doc(db, 'users', user.uid), \\\\{
  email: user.email,
  displayName: displayName,
  createdAt: new Date(),
  isActive: true
\\\\});

return user;

\\} catch (error) \\{ console.error('Error signing up: ', error); throw error; \\} \\};

const signInWithEmail = async (email, password) => \\{ try \\{ const userCredential = await signInWithEmailAndPassword(auth, email, password); return userCredential.user; \\} catch (error) \\{ console.error('Error signing in: ', error); throw error; \\} \\};

// Social Authentication const signInWithGoogle = async () => \\{ try \\{ const provider = new GoogleAuthProvider(); provider.addScope('profile'); provider.addScope('email');

const result = await signInWithPopup(auth, provider);
const user = result.user;

// Check if user document exists, create if not
const userDoc = await getDoc(doc(db, 'users', user.uid));
if (!userDoc.exists()) \\\\{
  await setDoc(doc(db, 'users', user.uid), \\\\{
    email: user.email,
    displayName: user.displayName,
    photoURL: user.photoURL,
    provider: 'google',
    createdAt: new Date(),
    isActive: true
  \\\\});
\\\\}

return user;

\\} catch (error) \\{ console.error('Error signing in with Google: ', error); throw error; \\} \\};

// Authentication state observer const useAuthState = () => \\{ const [user, setUser] = useState(null); const [loading, setLoading] = useState(true);

useEffect(() => \\{ const unsubscribe = onAuthStateChanged(auth, (user) => \\{ setUser(user); setLoading(false); \\});

return () => unsubscribe();

\\}, []);

return \\{ user, loading \\}; \\};

// Sign out const signOutUser = async () => \\{ try \\{ await signOut(auth); console.log('User signed out successfully'); \\} catch (error) \\{ console.error('Error signing out: ', error); throw error; \\} \\};

// Password reset const resetPassword = async (email) => \\{ try \\{ await sendPasswordResetEmail(auth, email); console.log('Password reset email sent'); \\} catch (error) \\{ console.error('Error sending password reset email: ', error); throw error; \\} \\};

// Update user profile const updateUserProfile = async (updates) => \\{ try \\{ const user = auth.currentUser; if (user) \\{ await updateProfile(user, updates);

  // Also update Firestore document
  await updateDoc(doc(db, 'users', user.uid), \\\\{
    ...updates,
    updatedAt: new Date()
  \\\\});
\\\\}

\\} catch (error) \\{ console.error('Error updating profile: ', error); throw error; \\} \\}; ```_

Sicherheitsregeln

```javascript // Firestore Security Rules // rules_version = '2'; // service cloud.firestore \\{ // match /databases/\\{database\\}/documents \\{ // // Users can read and write their own data // match /users/\\{userId\\} \\{ // allow read, write: if request.auth != null && request.auth.uid == userId; // \\} // // // Posts are readable by all authenticated users // // Only the author can write/update/delete // match /posts/\\{postId\\} \\{ // allow read: if request.auth != null; // allow create: if request.auth != null && // request.auth.uid == resource.data.authorId; // allow update, delete: if request.auth != null && // request.auth.uid == resource.data.authorId; // \\} // // // Comments can be created by authenticated users // // Only the author can update/delete their comments // match /posts/\\{postId\\}/comments/\\{commentId\\} \\{ // allow read: if request.auth != null; // allow create: if request.auth != null; // allow update, delete: if request.auth != null && // request.auth.uid == resource.data.authorId; // \\} // \\} // \\}

// Realtime Database Security Rules // \\{ // "rules": \\{ // "users": \\{ // "$uid": \\{ // ".read": "$uid === auth.uid", // ".write": "$uid === auth.uid" // \\} // \\}, // "posts": \\{ // ".read": "auth != null", // "$postId": \\{ // ".write": "auth != null && ( | // !data.exists() | | | // data.child('authorId').val() === auth.uid // )" // \\} // \\} // \\} // \\}

// Custom claims for role-based access const setUserRole = async (uid, role) => \\{ // This would be done in a Cloud Function with Admin SDK // admin.auth().setCustomUserClaims(uid, \\{ role: role \\}); \\};

// Check user role in security rules // allow write: if request.auth.token.role == 'admin'; ```_

Firebase Speicher

Datei Hochladen und Management

```javascript import \\{ getStorage, ref as storageRef, uploadBytes, uploadBytesResumable, getDownloadURL, deleteObject, listAll, getMetadata, updateMetadata \\} from 'firebase/storage';

const storage = getStorage();

// Upload file const uploadFile = async (file, path) => \\{ try \\{ const fileRef = storageRef(storage, path); const snapshot = await uploadBytes(fileRef, file); const downloadURL = await getDownloadURL(snapshot.ref);

console.log('File uploaded successfully');
return \\\\{ downloadURL, fullPath: snapshot.ref.fullPath \\\\};

\\} catch (error) \\{ console.error('Error uploading file: ', error); throw error; \\} \\};

// Upload with progress tracking const uploadFileWithProgress = (file, path, onProgress) => \\{ return new Promise((resolve, reject) => \\{ const fileRef = storageRef(storage, path); const uploadTask = uploadBytesResumable(fileRef, file);

uploadTask.on('state_changed',
  (snapshot) => \\\\{
    const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
    onProgress(progress);
  \\\\},
  (error) => \\\\{
    console.error('Upload error: ', error);
    reject(error);
  \\\\},
  async () => \\\\{
    try \\\\{
      const downloadURL = await getDownloadURL(uploadTask.snapshot.ref);
      resolve(\\\\{ downloadURL, fullPath: uploadTask.snapshot.ref.fullPath \\\\});
    \\\\} catch (error) \\\\{
      reject(error);
    \\\\}
  \\\\}
);

\\}); \\};

// Upload user avatar const uploadUserAvatar = async (userId, file) => \\{ try \\{ const path = avatars/$\\{userId\\}/$\\{file.name\\}; const result = await uploadFile(file, path);

// Update user profile with avatar URL
await updateDoc(doc(db, 'users', userId), \\\\{
  photoURL: result.downloadURL,
  updatedAt: new Date()
\\\\});

return result.downloadURL;

\\} catch (error) \\{ console.error('Error uploading avatar: ', error); throw error; \\} \\};

// Delete file const deleteFile = async (filePath) => \\{ try \\{ const fileRef = storageRef(storage, filePath); await deleteObject(fileRef); console.log('File deleted successfully'); \\} catch (error) \\{ console.error('Error deleting file: ', error); throw error; \\} \\};

// List files in directory const listFiles = async (path) => \\{ try \\{ const listRef = storageRef(storage, path); const result = await listAll(listRef);

const files = await Promise.all(
  result.items.map(async (itemRef) => \\\\{
    const url = await getDownloadURL(itemRef);
    const metadata = await getMetadata(itemRef);

    return \\\\{
      name: itemRef.name,
      fullPath: itemRef.fullPath,
      downloadURL: url,
      size: metadata.size,
      contentType: metadata.contentType,
      timeCreated: metadata.timeCreated
    \\\\};
  \\\\})
);

return files;

\\} catch (error) \\{ console.error('Error listing files: ', error); throw error; \\} \\}; ```_

Firebase Cloud Funktionen

Funktion Entwicklung und Bereitstellung

```javascript // Install Firebase Functions // npm install -g firebase-tools // firebase init functions

// functions/index.js const functions = require('firebase-functions'); const admin = require('firebase-admin');

admin.initializeApp();

// HTTP Cloud Function exports.helloWorld = functions.https.onRequest((request, response) => \\{ response.send('Hello from Firebase!'); \\});

// Firestore Trigger exports.onUserCreate = functions.firestore .document('users/\\{userId\\}') .onCreate(async (snap, context) => \\{ const userData = snap.data(); const userId = context.params.userId;

// Send welcome email
console.log(`New user created: $\\{userData.email\\}`);

// Create user stats document
await admin.firestore().collection('userStats').doc(userId).set(\\\\{
  postsCount: 0,
  likesReceived: 0,
  joinedAt: admin.firestore.FieldValue.serverTimestamp()
\\\\});

\\});

// Scheduled Function exports.dailyCleanup = functions.pubsub .schedule('0 2 * * *') // Every day at 2 AM .timeZone('America/New_York') .onRun(async (context) => \\{ // Clean up old data const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - 30);

const oldPosts = await admin.firestore()
  .collection('posts')
  .where('createdAt', '<', cutoffDate)
  .where('isDeleted', '==', true)
  .get();

const batch = admin.firestore().batch();
oldPosts.docs.forEach(doc => \\\\{
  batch.delete(doc.ref);
\\\\});

await batch.commit();
console.log(`Deleted $\\{oldPosts.size\\} old posts`);

\\});

// Callable Function exports.addAdminRole = functions.https.onCall(async (data, context) => \\{ // Check if user is authenticated and is admin if (!context.auth) \\{ throw new functions.https.HttpsError('unauthenticated', 'User must be authenticated'); \\}

if (!context.auth.token.admin) \\{ throw new functions.https.HttpsError('permission-denied', 'User must be admin'); \\}

try \\{ await admin.auth().setCustomUserClaims(data.uid, \\{ admin: true \\}); return \\{ message: 'Admin role added successfully' \\}; \\} catch (error) \\{ throw new functions.https.HttpsError('internal', 'Error adding admin role'); \\} \\});

// Deploy functions // firebase deploy --only functions ```_

Leistungsoptimierung und Best Practices

Datenmodellierung Best Practices

```javascript // Firestore data modeling principles

// 1. Denormalization for read efficiency const createPostWithAuthor = async (postData, authorData) => \\{ const postRef = await addDoc(collection(db, 'posts'), \\{ title: postData.title, content: postData.content, // Denormalize author data for efficient reads author: \\{ id: authorData.id, name: authorData.name, avatar: authorData.avatar \\}, createdAt: new Date(), likes: 0, commentsCount: 0 \\});

return postRef.id; \\};

// 2. Use subcollections for one-to-many relationships const addCommentToPost = async (postId, commentData) => \\{ const commentRef = await addDoc( collection(db, 'posts', postId, 'comments'), \\{ content: commentData.content, author: commentData.author, createdAt: new Date(), likes: 0 \\} );

// Update comment count in parent post await updateDoc(doc(db, 'posts', postId), \\{ commentsCount: increment(1) \\});

return commentRef.id; \\};

// 3. Use arrays for small lists, subcollections for large lists const addTagToPost = async (postId, tag) => \\{ await updateDoc(doc(db, 'posts', postId), \\{ tags: arrayUnion(tag) \\}); \\};

// 4. Optimize for your queries // Create composite indexes for compound queries // Index: collection: posts, fields: isPublished ASC, createdAt DESC

const getPublishedPosts = async () => \\{ const q = query( collection(db, 'posts'), where('isPublished', '==', true), orderBy('createdAt', 'desc'), limit(20) );

return await getDocs(q); \\}; ```_

Caching und Offline Support

```javascript import \\{ enableNetwork, disableNetwork \\} from 'firebase/firestore';

// Enable offline persistence import \\{ initializeFirestore, persistentLocalCache \\} from 'firebase/firestore';

const db = initializeFirestore(app, \\{ localCache: persistentLocalCache() \\});

// Handle online/offline state const handleNetworkChange = async (isOnline) => \\{ try \\{ if (isOnline) \\{ await enableNetwork(db); console.log('Network enabled'); \\} else \\{ await disableNetwork(db); console.log('Network disabled'); \\} \\} catch (error) \\{ console.error('Error changing network state: ', error); \\} \\};

// Listen for network changes window.addEventListener('online', () => handleNetworkChange(true)); window.addEventListener('offline', () => handleNetworkChange(false));

// Cache management const getCachedData = async (docRef) => \\{ try \\{ // Try to get from cache first const cachedDoc = await getDoc(docRef, \\{ source: 'cache' \\}); if (cachedDoc.exists()) \\{ return \\{ data: cachedDoc.data(), fromCache: true \\}; \\} \\} catch (error) \\{ console.log('No cached data available'); \\}

// Fallback to server const serverDoc = await getDoc(docRef, \\{ source: 'server' \\}); return \\{ data: serverDoc.exists() ? serverDoc.data() : null, fromCache: false \\}; \\}; ```_

Sicherheits- und Leistungsüberwachung

```javascript // Performance monitoring import \\{ getPerformance, trace \\} from 'firebase/performance';

const perf = getPerformance(app);

// Custom trace const measureDatabaseOperation = async (operation) => \\{ const customTrace = trace(perf, 'database_operation'); customTrace.start();

try \\{ const result = await operation(); customTrace.putAttribute('success', 'true'); return result; \\} catch (error) \\{ customTrace.putAttribute('success', 'false'); customTrace.putAttribute('error', error.message); throw error; \\} finally \\{ customTrace.stop(); \\} \\};

// Usage const getUserWithTrace = async (userId) => \\{ return await measureDatabaseOperation(async () => \\{ return await getDoc(doc(db, 'users', userId)); \\}); \\};

// Analytics import \\{ getAnalytics, logEvent \\} from 'firebase/analytics';

const analytics = getAnalytics(app);

// Log custom events const logUserAction = (action, parameters = \\{\\}) => \\{ logEvent(analytics, action, \\{ ...parameters, timestamp: Date.now() \\}); \\};

// Usage logUserAction('post_created', \\{ post_id: 'post123', category: 'technology' \\}); ```_

Firebase bietet Entwicklern eine leistungsstarke Plattform für den Aufbau moderner, skalierbarer Anwendungen mit Echtzeit-Funktionen, robuster Authentifizierung und nahtloser Offline-Unterstützung. Die Integration mit der Google Cloud Platform und der umfangreichen SDK-Unterstützung auf mehreren Plattformen macht es zu einer exzellenten Wahl für die schnelle Anwendungsentwicklung, von einfachen Prototypen bis hin zu komplexen, produktionsbereiten Anwendungen, die Millionen von Nutzern bedienen.