Project Templates
Social Network
Comment créer une plateforme de médias sociaux : guide étape par étape (2025)
71 min
introduction dans ce tutoriel, vous apprendrez à créer une plateforme de réseau social comme instagram en utilisant back4app comme service backend back4app fournit un backend parse server géré qui simplifie l'authentification des utilisateurs, le stockage des données, les téléchargements de fichiers et les fonctionnalités en temps réel sans nécessiter d'infrastructure serveur complexe en complétant ce tutoriel, vous construirez un réseau social complet avec authentification des utilisateurs (inscription, connexion, réinitialisation de mot de passe) gestion de profil création de publications avec téléchargements d'images interactions sociales (j'aime, commentaires) messagerie en temps réel avec indicateurs de saisie fonctionnalité de recherche de contenu aperçu du réseau socialinterface de chatprofil utilisateurpage de fil à tout moment, vous pouvez accéder au code complet sur github prérequis pour compléter ce tutoriel, vous aurez besoin de un compte back4app inscrivez vous pour un compte gratuit sur back4app com https //www back4app com/ node js et npm installés sur votre machine locale installez node js (version 14 x ou ultérieure) et npm depuis nodejs org https //nodejs org/ compréhension de base de javascript et react éditeur de code tout éditeur de code moderne comme visual studio code ou sublime text étape 1 — configuration de votre backend back4app tout d'abord, créons un nouveau projet back4app et configurons le schéma de base de données pour notre réseau social créer un nouveau projet back4app connectez vous à votre compte back4app et accédez au tableau de bord cliquez sur "créer une nouvelle application" entrez "back4gram" comme nom de votre application, sélectionnez la région de serveur la plus proche et cliquez sur "créer" comprendre le schéma de la base de données notre réseau social nécessite les classes suivantes dans back4app utilisateur (existe déjà par défaut dans parse) sera étendu avec des champs supplémentaires comme bio et avatar publication stocke les publications des utilisateurs, y compris le contenu textuel et les images commentaire stocke les commentaires sur les publications conversation représente une conversation de chat entre utilisateurs message messages individuels dans une conversation statutdesaisie suit quand les utilisateurs sont en train de taper dans une conversation créer des classes de base de données créons ces classes dans votre base de données back4app accédez à la section "base de données" dans votre tableau de bord back4app étendre la classe utilisateur cliquez sur la classe "utilisateur" qui existe déjà ajoutez les colonnes suivantes bio (type chaîne) avatar (type fichier) abonnés (type nombre, par défaut 0) suivant (type nombre, défaut 0) création de la classe post cliquez sur "créer une classe" entrez "post" comme nom de classe et sélectionnez "créer une classe vide" ajoutez les colonnes suivantes contenu (type chaîne) auteur (type pointeur vers utilisateur) image (type fichier) aime (type nombre, par défaut 0) aimépar (type tableau) créé à (type date, ajouté automatiquement) création de la classe comment créez une nouvelle classe nommée "commentaire" avec ces colonnes contenu (type chaîne) auteur (type pointeur vers utilisateur) publication (type pointeur vers la publication) créé à (type date, ajouté automatiquement) création de la classe conversation créez une nouvelle classe nommée "conversation" avec ces colonnes participants (type tableau) derniermessage (type chaîne) mis à jour (type date, ajouté automatiquement) création de la classe message créez une nouvelle classe nommée "message" avec ces colonnes texte (type chaîne) expéditeur (type pointeur vers utilisateur) conversation (type pointeur vers la conversation) créé à (type date, ajouté automatiquement) création de la classe typingstatus créez une nouvelle classe nommée "typingstatus" avec ces colonnes utilisateur (type pointeur vers utilisateur) conversation (type pointeur vers la conversation) estentraindetaper (type booléen) configuration des autorisations de classe pour sécuriser les données de votre application, configurez des listes de contrôle d'accès (acl) appropriées pour chaque classe accédez à la section "sécurité et clés" dans votre tableau de bord back4app sous "sécurité au niveau de la classe", configurez les autorisations pour chaque classe par exemple, sur la classe post accès en lecture public activé (tout le monde peut voir les publications) accès en écriture public activé (les utilisateurs authentifiés peuvent créer des publications) ajoutez des clps pour la mise à jour/suppression afin de restreindre à l'auteur uniquement configuration de livequery pour des fonctionnalités en temps réel pour activer des fonctionnalités en temps réel comme la messagerie et les indicateurs de saisie accédez à "paramètres du serveur" dans votre tableau de bord back4app sous "parse server", trouvez "livequery" et activez le ajoutez ces classes à surveiller par livequery message typingstatus post (pour des mises à jour en temps réel des likes et des commentaires) obtenir vos clés d'application vous aurez besoin de vos clés d'application back4app pour connecter votre frontend accédez à "paramètres de l'application" > "sécurité et clés" notez les clés suivantes id d'application clé javascript url du serveur url du serveur livequery clés de sécurité étape 2 — connecter votre frontend à back4app configurons la connexion entre votre frontend et le backend de back4app création de variables d'environnement créez un env local fichier à la racine de votre projet pour stocker vos identifiants back4app 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 remplacez les valeurs de remplacement par vos véritables identifiants back4app configurer le sdk parse avec back4app créez un fichier de configuration pour initialiser parse avec vos identifiants back4app // 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; ensuite, importez cette configuration dans le point d'entrée de votre application // 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> ); étape 3 — mise en œuvre de l'authentification avec back4app le serveur parse de back4app fournit un système de gestion des utilisateurs complet grâce à la parse user classe comprendre l'authentification des utilisateurs parse la classe parse user est conçue spécifiquement pour la gestion des utilisateurs stocke les identifiants des utilisateurs (nom d'utilisateur, email, mot de passe) gère l'état d'authentification gère automatiquement les jetons de session mise en œuvre de l'enregistrement des utilisateurs voici comment mettre en œuvre l'enregistrement des utilisateurs avec 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'}); } } }; implémentation de la connexion utilisateur voici comment implémenter la connexion utilisateur avec 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); } }; vérification de l'utilisateur actuel parse stocke automatiquement le jeton de session, vous permettant de vérifier si un utilisateur est déjà connecté // 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; } }; mise en œuvre de la réinitialisation du mot de passe back4app fournit un flux de réinitialisation de mot de passe intégré // 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); } }; étape 4 — création et affichage des publications maintenant, mettons en œuvre la création et la récupération de publications en utilisant back4app création de publications voici comment créer un nouveau post avec 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; } }; mécanismes clés de back4app parse object extend('post') fait référence à la classe post dans back4app new post() crée une nouvelle instance de la classe post parsefile save() télécharge le fichier dans le stockage de back4app newpost save() enregistre l'objet post dans back4app récupération des posts voici comment récupérer des posts depuis back4app // 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; } }; mécanismes clés de back4app new parse query(post) crée une requête sur la classe post query include('author') effectue une opération de type jointure pour récupérer des objets liés query descending('createdat') trie les résultats par date de création query limit() et query skip() implémente la pagination post get('image') url() obtient l'url d'un objet de fichier parse implémentation de la fonctionnalité j'aime voici comment implémenter les likes sur les publications // 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; } }; étape 5 — implémentation des commentaires sur les publications implémentons la fonctionnalité de commentaire en utilisant back4app créer des commentaires voici comment ajouter un commentaire à un post // 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; } }; récupérer les commentaires d'un post voici comment récupérer les commentaires d'un post spécifique // 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; } }; étape 6 — mise en œuvre des profils utilisateurs maintenant, mettons en œuvre des profils utilisateurs en utilisant back4app récupération des données utilisateur voici comment récupérer les données du profil utilisateur // 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; } }; mise à jour du profil utilisateur voici comment mettre à jour le profil d'un utilisateur // 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; } }; étape 7 — mise en œuvre de la messagerie en temps réel avec livequery maintenant, mettons en œuvre la messagerie en temps réel en utilisant la fonctionnalité livequery de back4app création de conversations voici comment créer une nouvelle conversation // 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; } }; envoyer des messages voici comment envoyer un message dans une conversation // 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; } }; configuration de livequery pour les messages voici comment s'abonner aux mises à jour de messages en temps réel // 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); } }; implémentation des indicateurs de saisie voici comment implémenter des indicateurs de saisie avec 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; } }; étape 8 — implémentation de la fonctionnalité de recherche implémentons la fonctionnalité de recherche en utilisant le système de requêtes de back4app recherche d'utilisateurs voici comment rechercher des utilisateurs // 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; } }; recherche de hashtags voici comment rechercher des publications avec des hashtags spécifiques // 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; } }; étape 9 — mise en œuvre des fonctionnalités avancées de back4app explorons quelques fonctionnalités avancées de back4app qui peuvent améliorer votre application de réseau social fonctions cloud back4app vous permet d'implémenter une logique côté serveur en utilisant des fonctions cloud ce sont des fonctions javascript qui s'exécutent sur le serveur et peuvent être appelées depuis votre application cliente voici un exemple d'une fonction cloud pour suivre les notifications de commentaires // 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 }); }); pour implémenter cela allez sur votre tableau de bord back4app naviguez vers "cloud code" > "fonctions cloud" créez une nouvelle fonction avec le code ci dessus déployez la fonction code cloud pour recherche avancée pour des fonctionnalités de recherche plus complexes, vous pouvez créer une fonction cloud // 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; }); pour appeler cette fonction depuis votre client // 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; } }; mise en œuvre des tâches en arrière plan pour des tâches récurrentes comme le calcul des sujets tendance, vous pouvez utiliser des tâches en arrière plan // 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"; }); pour configurer ce travail allez sur votre tableau de bord back4app naviguez vers "cloud code" > "background jobs" créez un nouveau travail avec le code ci dessus planifiez le pour qu'il s'exécute quotidiennement ou hebdomadairement utilisation des hooks de parse server back4app vous permet de mettre en œuvre des hooks côté serveur qui s'exécutent automatiquement avant ou après certaines opérations ceux ci sont utiles pour la validation des données, la modification ou le déclenchement d'effets secondaires // 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}`); }); mise en œuvre des notifications push back4app fournit un système de notification push robuste qui vous permet d'envoyer des notifications aux appareils de vos utilisateurs voici comment mettre en œuvre les notifications push tout d'abord, configurez une configuration push dans votre tableau de bord back4app allez dans "paramètres de l'application" > "push" configurez vos identifiants ios et/ou android envoyez une notification push lorsqu'un utilisateur reçoit un nouveau message // 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 }); } } }); utilisation du contrôle d'accès basé sur les rôles back4app fournit un système de contrôle d'accès basé sur les rôles qui vous permet de gérer les autorisations à un niveau plus granulaire // 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; } }; mise en œuvre des webhooks back4app vous permet de configurer des webhooks pour vous intégrer à des services externes // 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); } }); étape 10 — optimiser les performances de back4app à mesure que votre réseau social se développe, vous devrez optimiser votre backend back4app pour la performance et l'évolutivité cette section couvre des stratégies essentielles pour garantir que votre application reste rapide et réactive même lorsque votre base d'utilisateurs s'élargit optimisation de la base de données un design et des requêtes de base de données efficaces sont cruciaux pour la performance de l'application création d'index les index améliorent considérablement les performances des requêtes sur les champs fréquemment recherchés allez sur votre tableau de bord back4app naviguez vers "navigateur de base de données" > sélectionnez une classe (par exemple, post) cliquez sur l'onglet "index" créez des index pour les champs fréquemment recherchés // 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); } }; champs clés à indexer auteur dans la classe post pour des requêtes spécifiques à l'utilisateur plus rapides createdat pour un chargement de chronologie plus rapide nom d'utilisateur dans la classe utilisateur pour des recherches d'utilisateur plus rapides participants dans la classe conversation pour un filtrage de messages plus rapide optimisation des requêtes optimisez vos requêtes pour réduire la charge du serveur et le temps de réponse // 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; }; opérations par lots pour les opérations impliquant plusieurs objets, utilisez des opérations par lots pour réduire les appels api // 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; } }; mise en œuvre du cache implémentez la mise en cache côté client pour les données fréquemment consultées afin de réduire les appels api // 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); }; utilisation efficace de livequery livequery est puissant pour les fonctionnalités en temps réel mais doit être utilisé efficacement pour éviter les problèmes de performance // 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(); } }; meilleures pratiques pour livequery abonnez vous uniquement aux données qui nécessitent des mises à jour en temps réel limitez les champs que vous demandez avec select() désabonnez vous toujours lorsque les données ne sont plus nécessaires utilisez des contraintes pour réduire la portée des abonnements envisagez de combiner livequery avec des requêtes régulières pour le chargement initial des données optimisation de la gestion des fichiers une gestion efficace des fichiers est cruciale pour un réseau social avec des téléchargements d'images // 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 }; }; surveillance de votre application back4app back4app fournit plusieurs outils pour surveiller les performances de votre application analyse du tableau de bord fournit des statistiques d'utilisation de haut niveau surveillez les requêtes api, l'utilisation de stockage et les opérations de fichiers identifiez les modèles d'utilisation et les heures de pointe journaux fournissent des informations détaillées sur les opérations examinez les journaux du serveur pour des erreurs et des problèmes de performance filtrer les journaux par type pour isoler les problèmes métriques de performance suivez les temps de réponse et la santé du système surveillez la performance des requêtes identifiez les opérations lentes configurez des alertes pour être informé des problèmes potentiels allez dans "paramètres de l'application" > "alertes" dans votre tableau de bord back4app configurez des alertes pour utilisation élevée de l'api (approchant les limites de votre plan) piques de taux d'erreur (indiquant des problèmes d'application) temps d'arrêt du serveur (affectant tous les utilisateurs) utilisation de stockage (approchant la capacité) // 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; } }; stratégies de mise à l'échelle à mesure que votre application se développe, envisagez ces stratégies de mise à l'échelle mettez à niveau votre plan back4app passez à un niveau supérieur à mesure que votre base d'utilisateurs s'élargit surveillez l'utilisation et mettez à niveau avant d'atteindre les limites implémentez le sharding pour de grandes collections divisez les données entre plusieurs classes pour des ensembles de données très volumineux par exemple, divisez les messages par année ou par mois // 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; } }; implémenter un serveur de mise en cache utiliser redis ou d'autres solutions de mise en cache pour les données fréquemment accessibles implémenter via cloud code et services externes utiliser des réseaux de diffusion de contenu (cdn) configurer le cdn pour une livraison de fichiers plus rapide particulièrement important pour les images et les fichiers multimédias optimisations de sécurité la sécurité et la performance sont étroitement liées ces optimisations améliorent les deux implémenter les autorisations de pointeur utilisez les autorisations de pointeur pour restreindre l'accès aux objets associés cela permet des requêtes plus efficaces sans compromettre la sécurité // 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); } }; utilisez efficacement les acl de parse les acl fournissent une sécurité mais peuvent affecter les performances si elles sont trop utilisées envisagez d'utiliser des autorisations au niveau de la classe pour les cas courants et des acl pour les exceptions // 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; }; optimisation du serveur back4app optimisez la configuration de votre serveur parse dans back4app configurer les paramètres du serveur allez dans "paramètres de l'application" > "paramètres du serveur" ajustez les paramètres de délai d'attente pour les opérations de longue durée configurer les limites de requêtes maximales configurer la limitation de débit implémentez la limitation de débit pour prévenir les abus et garantir une utilisation équitable configurer via le code cloud comme montré précédemment en mettant en œuvre ces stratégies d'optimisation des performances, votre application de réseau social sera bien positionnée pour gérer la croissance et maintenir d'excellentes performances, même à mesure que votre base d'utilisateurs s'élargit n'oubliez pas de surveiller en continu les performances de votre application et d'apporter des améliorations progressives si nécessaire conclusion dans ce tutoriel, vous avez appris à créer une application de réseau social complète en utilisant back4app comme service backend vous avez mis en œuvre des fonctionnalités essentielles telles que authentification des utilisateurs et gestion des profils création de publications et interactions sociales messagerie en temps réel avec livequery fonctionnalité de recherche fonctionnalités avancées comme les cloud functions et les background jobs le parse server de back4app fournit une solution backend puissante et évolutive qui vous permet de vous concentrer sur la création de grandes expériences utilisateur sans vous soucier de l'infrastructure serveur complexe prochaines étapes pour améliorer davantage votre application de réseau social, envisagez mise en œuvre des notifications push en utilisant le service de notification push de back4app ajout d'analytique pour suivre l'engagement des utilisateurs configuration des options de stockage de fichiers pour des fichiers multimédias plus volumineux mise en œuvre de la modération de contenu en utilisant les cloud functions création d'une application mobile en utilisant react native avec le même backend back4app en tirant parti des fonctionnalités de back4app et en suivant les stratégies d'optimisation décrites dans ce tutoriel, vous pouvez créer un réseau social capable de gérer des milliers d'utilisateurs tout en maintenant des performances élevées ressources supplémentaires pour continuer à élargir vos connaissances sur back4app, voici quelques ressources précieuses documentation back4app documentation de back4app https //www back4app com/docs/get started/welcome guide javascript de parse https //docs parseplatform org/js/guide/ chaîne youtube de back4app https //www youtube com/c/back4app serveur parse et livequery documentation de parse server https //docs parseplatform org/parse server/guide/ guide des livequery https //docs parseplatform org/parse server/guide/#live queries sécurité et optimisation guide des autorisations au niveau de la classe https //docs parseplatform org/rest/guide/#class level permissions guide de sécurité acl https //docs parseplatform org/js/guide/#security optimisation des performances https //docs parseplatform org/js/guide/#performance fonctionnalités avancées guide du code cloud https //docs parseplatform org/cloudcode/guide/ travaux en arrière plan https //docs parseplatform org/cloudcode/guide/#cloud jobs notifications push https //docs parseplatform org/js/guide/#push notifications n'oubliez pas que construire un réseau social réussi est un processus itératif commencez par une base solide (que vous avez maintenant), recueillez les retours des utilisateurs et améliorez continuellement votre application en fonction des modèles d'utilisation réels nous espérons que ce tutoriel vous a fourni les connaissances et la confiance nécessaires pour créer des applications incroyables avec back4app bon codage !