Project Templates
Social Network
Wie man eine Social-Media-Plattform erstellt: Schritt-für-Schritt-Anleitung (2025)
70 min
einführung in diesem tutorial lernen sie, wie sie eine soziale netzwerkplattform wie instagram mit back4app als backend service erstellen back4app bietet ein verwaltetes parse server backend, das die benutzerauthentifizierung, datenspeicherung, datei uploads und echtzeitfunktionen vereinfacht, ohne dass eine komplexe serverinfrastruktur erforderlich ist durch den abschluss dieses tutorials erstellen sie ein vollständiges soziales netzwerk mit benutzerauthentifizierung (registrierung, anmeldung, passwort zurücksetzen) profilverwaltung beitrags erstellung mit bild uploads soziale interaktionen (likes, kommentare) echtzeit nachrichten mit tippindikatoren inhalts suchfunktionalität vorschau des sozialen netzwerkschat oberflächebenutzerprofilfeed seite zu jedem zeitpunkt können sie den vollständigen code auf github aufrufen voraussetzungen um dieses tutorial abzuschließen, benötigen sie ein back4app konto registrieren sie sich für ein kostenloses konto bei back4app com https //www back4app com/ node js und npm auf ihrem lokalen rechner installiert installieren sie node js (version 14 x oder höher) und npm von nodejs org https //nodejs org/ grundlegendes verständnis von javascript und react code editor jeder moderne code editor wie visual studio code oder sublime text schritt 1 — einrichten ihres back4app backends zuerst erstellen wir ein neues back4app projekt und richten das datenbankschema für unser soziales netzwerk ein erstellen eines neuen back4app projekts melden sie sich bei ihrem back4app konto an und navigieren sie zum dashboard klicken sie auf "eine neue app erstellen" geben sie "back4gram" als ihren app namen ein, wählen sie die nächstgelegene serverregion aus und klicken sie auf "erstellen" verstehen des datenbankschemas unser soziales netzwerk benötigt die folgenden klassen in back4app benutzer (existiert bereits standardmäßig in parse) wird mit zusätzlichen feldern wie bio und avatar erweitert beitrag speichert benutzerbeiträge einschließlich textinhalten und bildern kommentar speichert kommentare zu beiträgen unterhaltung stellt eine chatunterhaltung zwischen benutzern dar nachricht einzelne nachrichten innerhalb einer unterhaltung typingstatus verfolgt, wann benutzer in einer unterhaltung tippen erstellen von datenbankklassen lassen sie uns diese klassen in ihrer back4app datenbank erstellen navigieren sie zum abschnitt "datenbank" in ihrem back4app dashboard die benutzerklasse erweitern klicken sie auf die bereits vorhandene "benutzer" klasse fügen sie die folgenden spalten hinzu bio (typ zeichenfolge) avatar (typ datei) follower (typ zahl, standard 0) folgend (typ zahl, standard 0) die post klasse erstellen klicken sie auf "eine klasse erstellen" geben sie "post" als klassennamen ein und wählen sie "eine leere klasse erstellen" fügen sie die folgenden spalten hinzu inhalt (typ zeichenfolge) autor (typ zeiger auf benutzer) bild (typ datei) gefällt mir (typ zahl, standard 0) gemochtvon (typ array) erstelltam (typ datum, automatisch hinzugefügt) die kommentar klasse erstellen erstellen sie eine neue klasse mit dem namen "kommentar" mit diesen spalten inhalt (typ zeichenfolge) autor (typ zeiger auf benutzer) beitrag (typ zeiger auf beitrag) erstelltam (typ datum, automatisch hinzugefügt) die conversation klasse erstellen erstellen sie eine neue klasse mit dem namen "conversation" mit diesen spalten teilnehmer (typ array) letztenachricht (typ string) aktualisiertam (typ datum, automatisch hinzugefügt) die message klasse erstellen erstellen sie eine neue klasse mit dem namen "nachricht" mit diesen spalten text (typ zeichenfolge) absender (typ zeiger auf user) gespräch (typ zeiger auf gespräch) erstelltam (typ datum, automatisch hinzugefügt) erstellen der typingstatus klasse erstellen sie eine neue klasse mit dem namen "typingstatus" mit diesen spalten benutzer (typ zeiger auf benutzer) gespräch (typ zeiger auf gespräch) tippt (typ boolean) einrichten von klassenberechtigungen um ihre anwendungsdaten zu sichern, konfigurieren sie geeignete zugriffskontrolllisten (acls) für jede klasse navigieren sie zum abschnitt "sicherheit & schlüssel" in ihrem back4app dashboard unter "klassenebene sicherheit" konfigurieren sie die berechtigungen für jede klasse zum beispiel, in der post klasse öffentlicher lesezugriff aktiviert (jeder kann beiträge sehen) öffentlicher schreibzugriff aktiviert (authentifizierte benutzer können beiträge erstellen) fügen sie clps für update/löschen hinzu, um auf den autor zu beschränken einrichten von livequery für echtzeitfunktionen um echtzeitfunktionen wie messaging und tippindikatoren zu aktivieren navigieren sie zu "servereinstellungen" in ihrem back4app dashboard unter "parse server" finden sie "livequery" und aktivieren sie es fügen sie diese klassen hinzu, die von livequery überwacht werden sollen nachricht tippstatus beitrag (für echtzeit updates zu likes und kommentaren) erhalten ihrer anwendungs schlüssel sie benötigen ihre back4app anwendungsschlüssel, um ihre frontend zu verbinden navigieren sie zu "app einstellungen" > "sicherheit & schlüssel" notieren sie sich die folgenden schlüssel anwendungs id javascript schlüssel server url livequery server url sicherheitsschlüssel schritt 2 — verbindung ihres frontends mit back4app lassen sie uns die verbindung zwischen ihrem frontend und dem back4app backend einrichten umgebungsvariablen erstellen erstellen sie eine env local datei im stammverzeichnis ihres projekts, um ihre back4app anmeldeinformationen zu speichern react app parse app id=your application id react app parse js key=your javascript key react app parse server url=https //parseapi back4app com react app parse live query url=wss\ //your app id back4app io ersetzen sie die platzhalterwerte durch ihre tatsächlichen back4app anmeldeinformationen konfigurieren des parse sdk mit back4app erstellen sie eine konfigurationsdatei, um parse mit ihren back4app anmeldeinformationen zu initialisieren // src/utils/parseconfig js import parse from 'parse/dist/parse min js'; // initialize parse parse initialize( process env react app parse app id, process env react app parse js key ); parse serverurl = process env react app parse server url; // initialize live queries if (process env react app parse live query url) { parse livequeryserverurl = process env react app parse live query url; } export default parse; importieren sie dann diese konfiguration im einstiegspunkt ihrer app // src/index js import react from 'react'; import reactdom from 'react dom/client'; import ' /index css'; import app from ' /app'; import ' /utils/parseconfig'; // import parse configuration const root = reactdom createroot(document getelementbyid('root')); root render( \<react strictmode> \<app /> \</react strictmode> ); schritt 3 — implementierung der authentifizierung mit back4app der parse server von back4app bietet ein umfassendes benutzermanagementsystem über die parse user klasse verstehen der parse benutzerauthentifizierung die parse user klasse ist speziell für das benutzermanagement konzipiert speichert benutzeranmeldeinformationen (benutzername, e mail, passwort) verwaltet den authentifizierungsstatus verarbeitet sitzungstoken automatisch implementierung der benutzerregistrierung so implementieren sie die benutzerregistrierung mit parse // signup function const handlesignup = async () => { try { // create a new user const user = new parse user(); user set('username', username); user set('email', email); user set('password', password); // additional user data user set('bio', ''); user set('followers', 0); user set('following', 0); // sign up the user await user signup(); // success user is automatically logged in console log('user registered successfully'); // navigate to feed or home page navigate('/feed'); } catch (error) { // handle specific parse errors console error('error signing up ', error message); if (error code === 202) { seterrors({ errors, username 'username already taken'}); } else if (error code === 203) { seterrors({ errors, email 'email already in use'}); } } }; implementierung der benutzeranmeldung so implementierst du die benutzeranmeldung mit parse // login function const handlelogin = async () => { try { // log in the user const user = await parse user login(username, password); // success user is logged in console log('user logged in successfully ', user getusername()); // navigate to feed or home page navigate('/feed'); } catch (error) { // handle login errors console error('error logging in ', error message); setloginerror(error message); } }; überprüfung des aktuellen benutzers parse speichert automatisch das sitzungstoken, sodass du überprüfen kannst, ob ein benutzer bereits angemeldet ist // check if user is already logged in const checkcurrentuser = async () => { try { const currentuser = await parse user current(); if (currentuser) { console log('current user ', currentuser getusername()); return currentuser; } return null; } catch (error) { console error('error checking current user ', error); return null; } }; implementierung der passwortzurücksetzung back4app bietet einen integrierten ablauf zur passwortzurücksetzung // password reset function const handlepasswordreset = async () => { try { await parse user requestpasswordreset(email); // success email sent to user console log('password reset email sent'); setresetemailsent(true); } catch (error) { // handle reset errors console error('error requesting password reset ', error message); setreseterror(error message); } }; schritt 4 — erstellen und anzeigen von beiträgen jetzt lassen sie uns die erstellung und den abruf von beiträgen mit back4app implementieren beiträge erstellen so erstellen sie einen neuen beitrag mit parse // create post function const createpost = async () => { if (!postcontent trim() && !postimage) { console error('post must have content or image'); return; } try { // create a new post object const post = parse object extend('post'); const newpost = new post(); // set post content newpost set('content', postcontent); newpost set('author', parse user current()); newpost set('likes', 0); newpost set('likedby', \[]); // if there's an image, upload it if (postimage) { const parsefile = new parse file(postimage name, postimage); await parsefile save(); newpost set('image', parsefile); } // save the post await newpost save(); console log('post created successfully'); return newpost; } catch (error) { console error('error creating post ', error message); throw error; } }; wichtige back4app mechanismen parse object extend('post') verweist auf die post klasse in back4app new post() erstellt eine neue instanz der post klasse parsefile save() lädt die datei in den speicher von back4app hoch newpost save() speichert das beitragsobjekt in back4app beiträge abrufen so rufen sie beiträge von back4app ab // fetch posts function const fetchposts = async (page = 0, limit = 10) => { try { // create a query for the post class const post = parse object extend('post'); const query = new parse query(post); // include the author object (pointer) query include('author'); // sort by creation date, newest first query descending('createdat'); // pagination query limit(limit); query skip(page limit); // execute the query const results = await query find(); // process the results const posts = results map(post => ({ id post id, content post get('content'), image post get('image') ? post get('image') url() null, likes post get('likes') || 0, likedby post get('likedby') || \[], createdat post get('createdat'), author { id post get('author') id, username post get('author') get('username'), avatar post get('author') get('avatar') ? post get('author') get('avatar') url() null } })); return posts; } catch (error) { console error('error fetching posts ', error); throw error; } }; wichtige back4app mechanismen new parse query(post) erstellt eine abfrage auf der post klasse query include('author') führt eine join ähnliche operation durch, um verwandte objekte abzurufen query descending('createdat') sortiert die ergebnisse nach erstellungsdatum query limit() und query skip() implementiert die paginierung post get('image') url() holt die url eines parse dateiobjekts implementierung der like funktionalität so implementieren sie post likes // like/unlike post function const togglelike = async (postid) => { try { const currentuser = parse user current(); const userid = currentuser id; // get the post object const post = parse object extend('post'); const query = new parse query(post); const post = await query get(postid); // get current likes and likedby array const likedby = post get('likedby') || \[]; const isliked = likedby includes(userid); // update likes count and likedby array if (isliked) { // unlike remove user from likedby and decrement likes post set('likedby', likedby filter(id => id !== userid)); post set('likes', math max((post get('likes') || 1) 1, 0)); } else { // like add user to likedby and increment likes post set('likedby', \[ likedby, userid]); post set('likes', (post get('likes') || 0) + 1); } // save the updated post await post save(); return !isliked; // return new like status } catch (error) { console error('error toggling like ', error); throw error; } }; schritt 5 — implementierung von kommentaren zu posts lass uns die kommentarfunktion mit back4app implementieren kommentare erstellen so fügst du einen kommentar zu einem beitrag hinzu // add comment function const addcomment = async (postid, commentcontent) => { if (!commentcontent trim()) { console error('comment cannot be empty'); return; } try { // get the post object const post = parse object extend('post'); const postquery = new parse query(post); const post = await postquery get(postid); // create a new comment object const comment = parse object extend('comment'); const comment = new comment(); // set comment data comment set('content', commentcontent); comment set('author', parse user current()); comment set('post', post); // save the comment await comment save(); console log('comment added successfully'); return comment; } catch (error) { console error('error adding comment ', error); throw error; } }; kommentare für einen beitrag abrufen so rufst du kommentare für einen bestimmten beitrag ab // fetch comments function const fetchcomments = async (postid) => { try { // get the post object const post = parse object extend('post'); const postquery = new parse query(post); const post = await postquery get(postid); // create a query for comments const comment = parse object extend('comment'); const query = new parse query(comment); // find comments for this post query equalto('post', post); // include the author information query include('author'); // sort by creation date query ascending('createdat'); // execute the query const results = await query find(); // process the results const comments = results map(comment => ({ id comment id, content comment get('content'), createdat comment get('createdat'), author { id comment get('author') id, username comment get('author') get('username'), avatar comment get('author') get('avatar') ? comment get('author') get('avatar') url() null } })); return comments; } catch (error) { console error('error fetching comments ', error); throw error; } }; schritt 6 — implementierung von benutzerprofilen jetzt implementieren wir benutzerprofile mit back4app benutzerdaten abrufen so rufen sie die benutzerdaten des profils ab // fetch user profile function const fetchuserprofile = async (userid) => { try { // create a query for the user class const query = new parse query(parse user); // get the user by id const user = await query get(userid); // get user posts const post = parse object extend('post'); const postsquery = new parse query(post); postsquery equalto('author', user); postsquery include('author'); postsquery descending('createdat'); const posts = await postsquery find(); // process user data const userdata = { id user id, username user get('username'), bio user get('bio') || '', avatar user get('avatar') ? user get('avatar') url() null, followers user get('followers') || 0, following user get('following') || 0, posts posts map(post => ({ id post id, content post get('content'), image post get('image') ? post get('image') url() null, likes post get('likes') || 0, createdat post get('createdat') })) }; return userdata; } catch (error) { console error('error fetching user profile ', error); throw error; } }; benutzerprofil aktualisieren so aktualisieren sie das profil eines benutzers // update user profile function const updateuserprofile = async (profiledata) => { try { const currentuser = await parse user current(); // update profile fields if (profiledata bio !== undefined) { currentuser set('bio', profiledata bio); } if (profiledata avatarfile) { const parsefile = new parse file('avatar jpg', profiledata avatarfile); await parsefile save(); currentuser set('avatar', parsefile); } // save the updated user await currentuser save(); console log('profile updated successfully'); return currentuser; } catch (error) { console error('error updating profile ', error); throw error; } }; schritt 7 — implementierung der echtzeitkommunikation mit livequery jetzt implementieren wir die echtzeitkommunikation mit der livequery funktion von back4app erstellen von konversationen so erstellen sie eine neue konversation // create conversation function const createconversation = async (participantids) => { try { // ensure current user is included in participants const currentuser = await parse user current(); const allparticipantids = \[ new set(\[currentuser id, participantids])]; // check if conversation already exists const existingconversation = await findexistingconversation(allparticipantids); if (existingconversation) { return existingconversation; } // get user objects for all participants const participantpointers = await promise all( allparticipantids map(async (id) => { const userquery = new parse query(parse user); return await userquery get(id); }) ); // create new conversation const conversation = parse object extend('conversation'); const conversation = new conversation(); conversation set('participants', participantpointers); conversation set('lastmessage', ''); await conversation save(); console log('conversation created successfully'); return conversation; } catch (error) { console error('error creating conversation ', error); throw error; } }; // helper to find existing conversation const findexistingconversation = async (participantids) => { try { const conversation = parse object extend('conversation'); const query = new parse query(conversation); // this is a simplified approach in production you'd need more complex query const results = await query find(); for (const conversation of results) { const participants = conversation get('participants') || \[]; const participantids = participants map(p => p id); // check if arrays have same elements (regardless of order) if (participantids length === participantids length && participantids every(id => participantids includes(id))) { return conversation; } } return null; } catch (error) { console error('error finding existing conversation ', error); return null; } }; nachrichten senden so senden sie eine nachricht in einem gespräch // send message function const sendmessage = async (conversationid, messagetext) => { try { const currentuser = parse user current(); // get the conversation const conversation = parse object extend('conversation'); const conversationquery = new parse query(conversation); const conversation = await conversationquery get(conversationid); // create a new message const message = parse object extend('message'); const message = new message(); message set('text', messagetext); message set('sender', currentuser); message set('conversation', conversation); message set('read', false); await message save(); // update conversation with last message conversation set('lastmessage', messagetext); await conversation save(); console log('message sent successfully'); return message; } catch (error) { console error('error sending message ', error); throw error; } }; livequery für nachrichten einrichten so abonnieren sie echtzeit updates für nachrichten // subscribe to messages function const subscribetomessages = async (conversationid, onnewmessage) => { try { // create a query for messages in this conversation const message = parse object extend('message'); const query = new parse query(message); // get the conversation pointer const conversation = parse object extend('conversation'); const conversationpointer = new conversation(); conversationpointer id = conversationid; // set up query constraints query equalto('conversation', conversationpointer); query include('sender'); // subscribe to the query const subscription = await query subscribe(); // listen for create events (new messages) subscription on('create', (message) => { // process the message const newmessage = { id message id, text message get('text'), createdat message get('createdat'), sender { id message get('sender') id, username message get('sender') get('username'), avatar message get('sender') get('avatar') ? message get('sender') get('avatar') url() null }, read message get('read') }; // call the callback with the new message onnewmessage(newmessage); // mark the message as read if from another user if (message get('sender') id !== parse user current() id) { markmessageasread(message); } }); return subscription; } catch (error) { console error('error subscribing to messages ', error); throw error; } }; // helper to mark message as read const markmessageasread = async (message) => { try { message set('read', true); await message save(); } catch (error) { console error('error marking message as read ', error); } }; implementierung von tippindikatoren so implementieren sie tippindikatoren mit livequery // update typing status function const updatetypingstatus = async (conversationid, istyping) => { try { const currentuser = parse user current(); // get the conversation pointer const conversation = parse object extend('conversation'); const conversationpointer = new conversation(); conversationpointer id = conversationid; // check if typing status exists const typingstatus = parse object extend('typingstatus'); const query = new parse query(typingstatus); query equalto('conversation', conversationpointer); query equalto('user', currentuser); let typingstatus = await query first(); if (typingstatus) { // update existing status typingstatus set('istyping', istyping); } else { // create new status typingstatus = new typingstatus(); typingstatus set('conversation', conversationpointer); typingstatus set('user', currentuser); typingstatus set('istyping', istyping); } await typingstatus save(); } catch (error) { console error('error updating typing status ', error); } }; // subscribe to typing status function const subscribetotypingstatus = async (conversationid, ontypingstatuschange) => { try { // create a query for typing status in this conversation const typingstatus = parse object extend('typingstatus'); const query = new parse query(typingstatus); // get the conversation pointer const conversation = parse object extend('conversation'); const conversationpointer = new conversation(); conversationpointer id = conversationid; // set up query constraints query equalto('conversation', conversationpointer); query include('user'); // subscribe to the query const subscription = await query subscribe(); // listen for update events subscription on('update', (typingstatus) => { const user = typingstatus get('user'); const istyping = typingstatus get('istyping'); // call the callback with typing status ontypingstatuschange({ userid user id, username user get('username'), istyping }); }); // also listen for create events subscription on('create', (typingstatus) => { const user = typingstatus get('user'); const istyping = typingstatus get('istyping'); // call the callback with typing status ontypingstatuschange({ userid user id, username user get('username'), istyping }); }); return subscription; } catch (error) { console error('error subscribing to typing status ', error); throw error; } }; schritt 8 — implementierung der suchfunktionalität lassen sie uns die suchfunktionalität mit dem abfragesystem von back4app implementieren benutzersuche so suchen sie nach benutzern // search users function const searchusers = async (query, limit = 20) => { try { // create a query on the user class const userquery = new parse query(parse user); // search by username (case insensitive) userquery matches('username', new regexp(query, 'i')); // limit results to improve performance userquery limit(limit); // execute the query const users = await userquery find(); // process the results const userresults = users map(user => ({ id user id, username user get('username'), avatar user get('avatar') ? user get('avatar') url() null, bio user get('bio') || '' })); return userresults; } catch (error) { console error('error searching users ', error); throw error; } }; \### searching for posts here's how to search for posts by content ```javascript // search posts function const searchposts = async (query, limit = 20) => { try { // create a query on the post class const post = parse object extend('post'); const postquery = new parse query(post); // search for posts with content containing the query string postquery matches('content', new regexp(query, 'i')); // include the author information postquery include('author'); // sort by creation date (newest first) postquery descending('createdat'); // limit results postquery limit(limit); // execute the query const posts = await postquery find(); // process the results const postresults = posts map(post => ({ id post id, content post get('content'), image post get('image') ? post get('image') url() null, likes post get('likes') || 0, createdat post get('createdat'), author { id post get('author') id, username post get('author') get('username'), avatar post get('author') get('avatar') ? post get('author') get('avatar') url() null } })); return postresults; } catch (error) { console error('error searching posts ', error); throw error; } }; suche nach hashtags so suchen sie nach beiträgen mit bestimmten hashtags // search hashtags function const searchhashtags = async (tag, limit = 20) => { try { // remove # if present at the beginning const hashtagquery = tag startswith('#') ? tag substring(1) tag; // create a query on the post class const post = parse object extend('post'); const postquery = new parse query(post); // search for posts with content containing the hashtag // using word boundaries to find actual hashtags postquery matches('content', new regexp(`#${hashtagquery}\\\b`, 'i')); // include the author information postquery include('author'); // sort by creation date (newest first) postquery descending('createdat'); // limit results postquery limit(limit); // execute the query const posts = await postquery find(); // process the results const hashtagresults = posts map(post => ({ id post id, content post get('content'), image post get('image') ? post get('image') url() null, likes post get('likes') || 0, createdat post get('createdat'), author { id post get('author') id, username post get('author') get('username'), avatar post get('author') get('avatar') ? post get('author') get('avatar') url() null } })); return hashtagresults; } catch (error) { console error('error searching hashtags ', error); throw error; } }; schritt 9 — implementierung fortgeschrittener back4app funktionen lass uns einige fortgeschrittene back4app funktionen erkunden, die deine social network anwendung verbessern können cloud funktionen back4app ermöglicht es ihnen, serverseitige logik mit cloud funktionen zu implementieren dies sind javascript funktionen, die auf dem server ausgeführt werden und von ihrer client app aufgerufen werden können hier ist ein beispiel für eine cloud funktion zur verfolgung von kommentarbenachrichtigungen // in your back4app cloud code section parse cloud aftersave("comment", async (request) => { // only run for new comments, not updates if (request original) return; const comment = request object; const post = comment get("post"); const commenter = request user; // skip if user is commenting on their own post const postquery = new parse query("post"); const fullpost = await postquery get(post id, { usemasterkey true }); const postauthor = fullpost get("author"); if (postauthor id === commenter id) return; // create a notification const notification = parse object extend("notification"); const notification = new notification(); notification set("type", "comment"); notification set("fromuser", commenter); notification set("touser", postauthor); notification set("post", post); notification set("read", false); await notification save(null, { usemasterkey true }); }); um dies zu implementieren gehen sie zu ihrem back4app dashboard navigieren sie zu "cloud code" > "cloud functions" erstellen sie eine neue funktion mit dem obigen code die funktion bereitstellen cloud code für erweiterte suche für komplexere suchfunktionen können sie eine cloud funktion erstellen // in your back4app cloud code section parse cloud define("advancedsearch", async (request) => { const { query, type, limit = 20 } = request params; if (!query) { throw new error("search query is required"); } let results = \[]; switch (type) { case 'users' const userquery = new parse query(parse user); userquery matches('username', new regexp(query, 'i')); userquery limit(limit); results = await userquery find({ usemasterkey true }); break; case 'posts' const post = parse object extend('post'); const postquery = new parse query(post); postquery matches('content', new regexp(query, 'i')); postquery include('author'); postquery limit(limit); results = await postquery find({ usemasterkey true }); break; default throw new error("invalid search type"); } return results; }); um diese funktion von ihrem client aus aufzurufen // call the advanced search cloud function const calladvancedsearch = async (query, type, limit = 20) => { try { const results = await parse cloud run('advancedsearch', { query, type, limit }); return results; } catch (error) { console error('error calling advanced search ', error); throw error; } }; hintergrundjobs implementieren für wiederkehrende aufgaben wie die berechnung von trendthemen können sie hintergrundjobs verwenden // in your back4app cloud code section parse cloud job("calculatetrendingtopics", async () => { // get posts from the last 7 days const post = parse object extend("post"); const query = new parse query(post); const oneweekago = new date(); oneweekago setdate(oneweekago getdate() 7); query greaterthan('createdat', oneweekago); // limit to a reasonable number for analysis query limit(1000); const posts = await query find({ usemasterkey true }); // extract hashtags and count occurrences const hashtagcounts = {}; posts foreach(post => { const content = post get('content') || ''; const hashtags = content match(/#(\w+)/g) || \[]; hashtags foreach(hashtag => { const tag = hashtag tolowercase(); hashtagcounts\[tag] = (hashtagcounts\[tag] || 0) + 1; }); }); // convert to array and sort by count const trendingarray = object entries(hashtagcounts) map((\[hashtag, count]) => ({ hashtag, count })) sort((a, b) => b count a count) slice(0, 10); // get top 10 // save to a trendingtopics class const trendingtopics = parse object extend("trendingtopics"); const trending = new trendingtopics(); trending set("topics", trendingarray); trending set("calculatedat", new date()); await trending save(null, { usemasterkey true }); return "trending topics calculated successfully"; }); um diesen job einzurichten gehe zu deinem back4app dashboard navigiere zu "cloud code" > "hintergrundjobs" erstelle einen neuen job mit dem obigen code plane ihn, täglich oder wöchentlich ausgeführt zu werden verwendung von parse server hooks back4app ermöglicht es ihnen, serverseitige hooks zu implementieren, die automatisch vor oder nach bestimmten operationen ausgeführt werden diese sind nützlich für die datenvalidierung, modifikation oder das auslösen von nebeneffekten // beforesave hook to sanitize post content parse cloud beforesave("post", async (request) => { const post = request object; let content = post get("content"); // sanitize content (example remove profanity) const profanitylist = \["badword1", "badword2", "badword3"]; profanitylist foreach(word => { const regex = new regexp(word, "gi"); content = content replace(regex, " "); }); // update the content post set("content", content); }); // afterdelete hook to clean up related data parse cloud afterdelete("post", async (request) => { const post = request object; const postid = post id; // delete all comments associated with this post const comment = parse object extend("comment"); const query = new parse query(comment); query equalto("post", post); const comments = await query find({ usemasterkey true }); await parse object destroyall(comments, { usemasterkey true }); console log(`deleted ${comments length} comments for post ${postid}`); }); implementierung von push benachrichtigungen back4app bietet ein robustes push benachrichtigungssystem, mit dem sie benachrichtigungen an die geräte ihrer benutzer senden können so implementieren sie push benachrichtigungen zuerst richten sie eine push konfiguration in ihrem back4app dashboard ein gehen sie zu "app einstellungen" > "push" konfigurieren sie ihre ios und/oder android anmeldeinformationen senden sie eine push benachrichtigung, wenn ein benutzer eine neue nachricht erhält // in your cloud code parse cloud aftersave("message", async (request) => { const message = request object; const conversation = message get("conversation"); const sender = message get("sender"); // get the conversation to find recipients const conversationquery = new parse query("conversation"); const fullconversation = await conversationquery get(conversation id, { usemasterkey true }); // get all participants const participants = fullconversation get("participants") || \[]; // send notification to all participants except the sender for (const participant of participants) { if (participant id !== sender id) { // create a query for this user's installations const pushquery = new parse query(parse installation); pushquery equalto("user", participant); // send the push notification await parse push send({ where pushquery, data { alert `new message from ${sender get("username")}`, sound "default", badge "increment", sender sender id, messageid message id, conversationid conversation id } }, { usemasterkey true }); } } }); verwendung von rollenbasiertem zugriffskontrollsystem back4app bietet ein rollenbasiertes zugriffskontrollsystem, mit dem sie berechtigungen auf einer detaillierteren ebene verwalten können // create an admin role const createadminrole = async (adminuser) => { try { // create a new role const adminrole = new parse role("administrator", new parse acl()); // set initial users of this role adminrole getusers() add(adminuser); // save the role await adminrole save(null, { usemasterkey true }); console log("admin role created successfully"); return adminrole; } catch (error) { console error("error creating admin role ", error); throw error; } }; // set permissions for posts to be moderated by admins const setpostmoderatorpermissions = async () => { try { // get the admin role const rolequery = new parse query(parse role); rolequery equalto("name", "administrator"); const adminrole = await rolequery first({ usemasterkey true }); // set class level permissions const schema = new parse schema("post"); // add class level permissions for admin role await schema setclp({ get { " " true }, find { " " true }, create { " " true }, update { "role\ administrator" true, "" true }, // creator and admins can update delete { "role\ administrator" true, "" true }, // creator and admins can delete addfield { "role\ administrator" true } }); await schema update(); console log("admin permissions for post class set successfully"); } catch (error) { console error("error setting admin permissions ", error); throw error; } }; implementierung von webhooks back4app ermöglicht es ihnen, webhooks einzurichten, um mit externen diensten zu integrieren // example cloud function that calls an external webhook parse cloud aftersave("post", async (request) => { const post = request object; // only trigger for new posts if (request original) return; try { // get author information const author = post get("author"); await author fetch({ usemasterkey true }); // prepare data for webhook const webhookdata = { postid post id, content post get("content"), authorname author get("username"), createdat post get("createdat") }; // call external webhook (example notify a content moderation service) const response = await parse cloud httprequest({ method 'post', url 'https //your webhook url com/new post', headers { 'content type' 'application/json' }, body webhookdata }); console log("webhook notification sent successfully ", response data); } catch (error) { console error("error sending webhook notification ", error); } }); schritt 10 — optimierung der back4app leistung wenn ihr soziales netzwerk wächst, müssen sie ihr back4app backend für leistung und skalierbarkeit optimieren dieser abschnitt behandelt wesentliche strategien, um sicherzustellen, dass ihre anwendung schnell und reaktionsschnell bleibt, auch wenn ihre benutzerbasis wächst datenbankoptimierung effizientes datenbankdesign und abfragen sind entscheidend für die anwendungsleistung indizes erstellen indizes verbessern die abfrageleistung bei häufig durchsuchen feldern erheblich gehe zu deinem back4app dashboard navigiere zu "datenbank browser" > wähle eine klasse (z b post) klicke auf den tab "indizes" erstelle indizes für häufig durchsuchen felder // example creating indexes programmatically const createpostindexes = async () => { try { const schema = new parse schema('post'); // add an index on the author field await schema addindex('author index', { author 1 }); // add an index on createdat for timeline queries await schema addindex('createdat index', { createdat 1 }); // add a compound index for author + createdat await schema addindex('author date index', { author 1, createdat 1 }); await schema update(); console log('indexes created successfully'); } catch (error) { console error('error creating indexes ', error); } }; wichtige felder zum indizieren autor in der post klasse für schnellere benutzerspezifische abfragen createdat für schnellere zeitlinienladezeiten benutzername in der benutzerklasse für schnellere benutzersuchen teilnehmer in der konversationsklasse für schnellere nachrichtenfilterung abfrageoptimierung optimieren sie ihre abfragen, um die serverlast und die antwortzeit zu reduzieren // bad fetches all fields and doesn't use limit const fetchuserposts = async (userid) => { const query = new parse query('post'); query equalto('author', userid); const results = await query find(); return results; }; // good only fetches needed fields and uses limit const fetchuserposts = async (userid, page = 0, limit = 20) => { const post = parse object extend('post'); const query = new parse query(post); // get user pointer const userpointer = { type 'pointer', classname ' user', objectid userid }; // only get posts for this user query equalto('author', userpointer); // only select fields we need query select('content', 'image', 'likes', 'createdat'); // sort by date, newest first query descending('createdat'); // implement pagination query limit(limit); query skip(page limit); const results = await query find(); return results; }; batch operationen für operationen, die mehrere objekte betreffen, verwenden sie batch operationen, um api aufrufe zu reduzieren // update multiple posts in a single request const updatemultipleposts = async (postids, updatedata) => { try { const post = parse object extend('post'); const posts = postids map(id => { const post = new post(); post id = id; return post; }); // set the same update data on all posts posts foreach(post => { object entries(updatedata) foreach((\[key, value]) => { post set(key, value); }); }); // save all posts in a single request await parse object saveall(posts); console log('all posts updated successfully'); } catch (error) { console error('error updating posts ', error); throw error; } }; // delete multiple comments in a single request const deletemultiplecomments = async (commentids) => { try { const comment = parse object extend('comment'); const comments = commentids map(id => { const comment = new comment(); comment id = id; return comment; }); // delete all comments in a single request await parse object destroyall(comments); console log('all comments deleted successfully'); } catch (error) { console error('error deleting comments ', error); throw error; } }; caching implementieren implementieren sie das caching auf der client seite für häufig abgerufene daten, um api aufrufe zu reduzieren // caching user profiles const userprofilecache = new map(); const cache expiry = 10 60 1000; // 10 minutes in milliseconds const getuserprofile = async (userid, forcerefresh = false) => { // check if we have a valid cache entry const now = date now(); const cacheentry = userprofilecache get(userid); if (!forcerefresh && cacheentry && (now cacheentry timestamp < cache expiry)) { console log('using cached user profile'); return cacheentry data; } try { // fetch from back4app const query = new parse query(parse user); const user = await query get(userid); // process user data const userdata = { id user id, username user get('username'), bio user get('bio') || '', avatar user get('avatar') ? user get('avatar') url() null, followers user get('followers') || 0, following user get('following') || 0 }; // store in cache with timestamp userprofilecache set(userid, { data userdata, timestamp now }); return userdata; } catch (error) { console error('error fetching user profile ', error); // return cached data even if expired in case of error if (cacheentry) { console log('using expired cache due to error'); return cacheentry data; } throw error; } }; // clear cache for a user when their profile is updated const invalidateusercache = (userid) => { userprofilecache delete(userid); }; livequery effizient nutzen livequery ist leistungsstark für echtzeitfunktionen, sollte jedoch effizient genutzt werden, um leistungsprobleme zu vermeiden // efficient livequery usage const setupefficientlivequery = async (conversationid) => { try { // only subscribe to messages in the active conversation if (!conversationid) return null; // create a focused query const message = parse object extend('message'); const query = new parse query(message); // get the conversation pointer const conversation = parse object extend('conversation'); const conversationpointer = new conversation(); conversationpointer id = conversationid; // only get messages for this conversation query equalto('conversation', conversationpointer); // only include necessary fields query select('text', 'sender', 'createdat'); // limit initial results query limit(50); query descending('createdat'); // create subscription const subscription = await query subscribe(); subscription on('create', (message) => { // handle new message console log('new message ', message get('text')); // update ui with new message }); // unsubscribe when switching conversations return subscription; } catch (error) { console error('error setting up livequery ', error); return null; } }; // always unsubscribe when done const cleanuplivequery = (subscription) => { if (subscription) { subscription unsubscribe(); } }; best practices für livequery abonnieren sie nur daten, die echtzeit updates benötigen begrenzen sie die felder, die sie mit select() immer abmelden, wenn die daten nicht mehr benötigt werden verwenden sie einschränkungen, um den umfang der abonnements einzugrenzen erwägen sie, livequery mit regulären abfragen für das initiale laden von daten zu kombinieren optimierung der dateiverwaltung effiziente dateiverwaltung ist entscheidend für ein soziales netzwerk mit bild uploads // resize images before upload to reduce storage and bandwidth const uploadresizedimage = async (originalfile, maxwidth = 1200, maxheight = 1200) => { return new promise((resolve, reject) => { try { const reader = new filereader(); reader onload = (event) => { const img = new image(); img onload = () => { // calculate new dimensions let width = img width; let height = img height; if (width > maxwidth) { height = math round(height (maxwidth / width)); width = maxwidth; } if (height > maxheight) { width = math round(width (maxheight / height)); height = maxheight; } // create canvas for resizing const canvas = document createelement('canvas'); canvas width = width; canvas height = height; // draw resized image const ctx = canvas getcontext('2d'); ctx drawimage(img, 0, 0, width, height); // convert to blob canvas toblob(async (blob) => { const resizedfile = new file(\[blob], originalfile name, { type originalfile type, lastmodified date now() }); // upload to back4app const parsefile = new parse file(resizedfile name, resizedfile); await parsefile save(); resolve(parsefile); }, originalfile type, 0 8); // 0 8 quality for jpeg }; img src = event target result; }; reader readasdataurl(originalfile); } catch (error) { reject(error); } }); }; // use thumbnails for preview images const createthumbnailversion = async (originalfile, thumbnailwidth = 200) => { // similar to above but creating a smaller thumbnail // // return both original and thumbnail return { original originalparsefile, thumbnail thumbnailparsefile }; }; überwachung ihrer back4app app back4app bietet mehrere tools zur überwachung der anwendungsleistung dashboard analytik bietet hochrangige nutzungsstatistiken überwachen sie api anfragen, speichernutzung und dateioperationen nutzungsmuster und spitzenzeiten identifizieren protokolle bieten detaillierte informationen zu operationen überprüfen sie die serverprotokolle auf fehler und leistungsprobleme protokolle nach typ filtern, um probleme zu isolieren leistungskennzahlen reaktionszeiten und systemgesundheit verfolgen überwachen sie die abfrageleistung langsame operationen identifizieren konfigurieren sie benachrichtigungen, um über potenzielle probleme informiert zu werden gehen sie zu "app einstellungen" > "benachrichtigungen" in ihrem back4app dashboard richten sie benachrichtigungen für ein hohe api nutzung (nahe an ihren planlimits) spitzen bei der fehlerquote (die auf anwendungsprobleme hinweisen) serverausfall (der alle benutzer betrifft) speichernutzung (nahe an der kapazität) // implementing custom logging for performance monitoring const logperformance = async (operation, starttime) => { const duration = date now() starttime; // log to back4app const performancelog = parse object extend('performancelog'); const log = new performancelog(); log set('operation', operation); log set('duration', duration); log set('user', parse user current() ? parse user current() id 'anonymous'); log set('timestamp', new date()); await log save(null, { usemasterkey true }); // log locally too console log(`performance ${operation} took ${duration}ms`); }; // example usage const fetchtimelineposts = async () => { const starttime = date now(); try { // query code here // // calculate and log performance await logperformance('fetchtimelineposts', starttime); return results; } catch (error) { console error('error ', error); throw error; } }; skalierungsstrategien wenn ihre anwendung wächst, ziehen sie diese skalierungsstrategien in betracht upgrade ihren back4app plan wechseln sie zu einer höheren stufe, wenn ihre benutzerbasis wächst überwachen sie die nutzung und aktualisieren sie, bevor sie die grenzen erreichen implementieren sie sharding für große sammlungen teilen sie daten über mehrere klassen für sehr große datensätze zum beispiel, teilen sie nachrichten nach jahr oder monat // example of sharded messages implementation const sendshardedmessage = async (conversationid, text, sender) => { try { // determine which shard to use (e g , by current month) const now = new date(); const shardname = `message ${now\ getfullyear()} ${now\ getmonth() + 1}`; // create dynamic class reference const messageshard = parse object extend(shardname); const message = new messageshard(); // create a pointer to the conversation const conversation = parse object extend('conversation'); const conversationpointer = new conversation(); conversationpointer id = conversationid; // set message data message set('conversation', conversationpointer); message set('text', text); message set('sender', sender); // save to appropriate shard await message save(); return message; } catch (error) { console error('error sending sharded message ', error); throw error; } }; // fetch messages across shards const fetchshardedmessages = async (conversationid, limit = 50) => { try { // get list of all message shards const shards = await getmessageshardnames(); // create a query for each shard const queries = shards map(shardname => { const messageshard = parse object extend(shardname); const query = new parse query(messageshard); // create a pointer to the conversation const conversation = parse object extend('conversation'); const conversationpointer = new conversation(); conversationpointer id = conversationid; query equalto('conversation', conversationpointer); return query; }); // combine queries const mainquery = parse query or( queries); mainquery descending('createdat'); mainquery limit(limit); return await mainquery find(); } catch (error) { console error('error fetching sharded messages ', error); throw error; } }; caching server implementieren verwenden sie redis oder andere caching lösungen für häufig abgerufene daten implementierung über cloud code und externe dienste content delivery networks (cdns) verwenden cdn für schnellere dateilieferung konfigurieren besonders wichtig für bilder und mediendateien sicherheitsoptimierungen sicherheit und leistung sind eng miteinander verbunden diese optimierungen verbessern beides implementiere zeigerberechtigungen verwende zeigerberechtigungen, um den zugriff auf verwandte objekte einzuschränken dies ermöglicht effizientere abfragen, ohne die sicherheit zu opfern // set up pointer permissions const setuppointerpermissions = async () => { try { // get the message class schema const schema = new parse schema('message'); // add pointer permissions only conversation participants can access messages const pointerpermissions = { 'conversation' { 'read' { 'participantsfield' 'participants' } } }; // update the schema with pointer permissions await schema addpointerpermissions(pointerpermissions); await schema update(); console log('pointer permissions set successfully'); } catch (error) { console error('error setting pointer permissions ', error); } }; verwende parse acls effizient acls bieten sicherheit, können aber die leistung beeinträchtigen, wenn sie übermäßig verwendet werden erwäge die verwendung von klassenebenenberechtigungen für häufige fälle und acls für ausnahmen // efficient acl usage set default acl parse setdefaultacl(new parse acl({ publicreadaccess true }), true); // only use specific acls for private content const createprivatepost = async (content, image) => { const currentuser = parse user current(); // create a new private post const post = parse object extend('post'); const post = new post(); // set post data post set('content', content); post set('author', currentuser); if (image) { const parsefile = new parse file(image name, image); await parsefile save(); post set('image', parsefile); } // create private acl const privateacl = new parse acl(currentuser); // only the creator can read and write privateacl setreadaccess(currentuser id, true); privateacl setwriteaccess(currentuser id, true); // set the acl post setacl(privateacl); // save the post await post save(); return post; }; back4app server optimierung optimieren sie ihre parse server konfiguration in back4app serverparameter konfigurieren gehen sie zu "app einstellungen" > "servereinstellungen" timeout einstellungen für langlaufende operationen anpassen maximale anforderungsgrenzen konfigurieren rate limiting einrichten implementieren sie rate limiting, um missbrauch zu verhindern und eine faire nutzung sicherzustellen konfigurieren sie über cloud code, wie zuvor gezeigt durch die implementierung dieser strategien zur leistungsoptimierung wird ihre social network anwendung gut positioniert sein, um wachstum zu bewältigen und eine hervorragende leistung aufrechtzuerhalten, selbst wenn ihre benutzerbasis wächst denken sie daran, die leistung ihrer anwendung kontinuierlich zu überwachen und schrittweise verbesserungen vorzunehmen, wenn dies erforderlich ist fazit in diesem tutorial haben sie gelernt, wie man eine vollständige social network anwendung mit back4app als backend service erstellt sie haben grundlegende funktionen implementiert wie benutzerauthentifizierung und profilverwaltung beitragserstellung und soziale interaktionen echtzeit nachrichtenübermittlung mit livequery suchfunktionalität erweiterte funktionen wie cloud funktionen und hintergrundjobs der parse server von back4app bietet eine leistungsstarke und skalierbare backend lösung, die es ihnen ermöglicht, sich auf den aufbau großartiger benutzererlebnisse zu konzentrieren, ohne sich um komplexe serverinfrastrukturen kümmern zu müssen nächste schritte um ihre social network anwendung weiter zu verbessern, ziehen sie in betracht implementierung von push benachrichtigungen unter verwendung des push dienstes von back4app hinzufügen von analysen zur verfolgung des benutzerengagements einrichten von dateispeicheroptionen für größere mediendateien implementierung von inhaltsmoderation unter verwendung von cloud funktionen erstellung einer mobilen app unter verwendung von react native mit demselben back4app backend durch die nutzung der funktionen von back4app und die befolgung der in diesem tutorial skizzierten optimierungsstrategien können sie ein soziales netzwerk aufbauen, das in der lage ist, tausende von benutzern zu verwalten und dabei eine hohe leistung aufrechtzuerhalten zusätzliche ressourcen um ihr wissen über back4app weiter auszubauen, finden sie hier einige wertvolle ressourcen back4app dokumentation back4app dokumentation https //www back4app com/docs/get started/welcome parse javascript anleitung https //docs parseplatform org/js/guide/ back4app youtube kanal https //www youtube com/c/back4app parse server und livequery parse server dokumentation https //docs parseplatform org/parse server/guide/ livequery anleitung https //docs parseplatform org/parse server/guide/#live queries sicherheit und optimierung leitfaden zu klassenebene berechtigungen https //docs parseplatform org/rest/guide/#class level permissions acl sicherheitsleitfaden https //docs parseplatform org/js/guide/#security leistungsoptimierung https //docs parseplatform org/js/guide/#performance erweiterte funktionen cloud code anleitung https //docs parseplatform org/cloudcode/guide/ hintergrundjobs https //docs parseplatform org/cloudcode/guide/#cloud jobs push benachrichtigungen https //docs parseplatform org/js/guide/#push notifications denken sie daran, dass der aufbau eines erfolgreichen sozialen netzwerks ein iterativer prozess ist beginnen sie mit einer soliden grundlage (die sie jetzt haben), sammeln sie benutzerfeedback und verbessern sie ihre anwendung kontinuierlich basierend auf realen nutzungsmustern wir hoffen, dass dieses tutorial ihnen das wissen und das vertrauen vermittelt hat, um erstaunliche anwendungen mit back4app zu erstellen viel spaß beim programmieren!