Lignes directrices pratiques pour le développement d'applications React à grande échelle. Planification, actions, sources de données et API

Aujourd'hui, nous portons à votre attention la première partie de la traduction du matériel, qui est consacrée au développement d'applications React à grande échelle. Lorsque vous créez une application d'une page à l'aide de React, il est très facile de gâcher sa base de code. Cela complique le débogage de l'application, rend difficile la mise à jour ou l'extension du code du projet.



Il existe de nombreuses bonnes bibliothèques dans l'écosystème React qui peuvent être utilisées pour gérer certains aspects d'une application. Nous allons nous attarder sur certains d'entre eux en détail. De plus, quelques recommandations pratiques seront données ici. Si le projet doit bien évoluer, il sera utile de suivre ces recommandations dès le tout début des travaux. Dans cette partie de la traduction, nous parlerons de la planification, des actions, des sources de données et de l'API. La première étape du développement d'applications React à grande échelle, que nous examinerons, est la planification.

Partie 1: Lignes directrices pratiques pour le développement d'applications React à grande échelle. Planification, actions, sources de données et API

Partie 2: Lignes directrices pratiques pour le développement d'applications React à grande échelle. Partie 2: gestion des états, routage


Planification


Le plus souvent, les développeurs sautent cette étape du travail sur l'application. Cela est dû au fait qu'au cours du processus de planification, aucun travail n'est effectué sur l'écriture de code. Mais l'importance de cette étape ne peut être sous-estimée. Vous saurez bientôt pourquoi il en est ainsi.

▍Pourquoi prévoyez-vous lors du développement d'applications?


Le développement de logiciels nécessite la coordination de nombreux processus. En même temps, tout devient très facilement hors de contrôle. Les obstacles et les incertitudes rencontrés dans le processus de développement peuvent compromettre le calendrier du projet.

La phase de planification du projet peut vous aider à respecter les délais. A ce stade, «posez sur les étagères» toutes les fonctionnalités que l'application devrait avoir. Il est beaucoup plus facile de prévoir le temps qu'il faudra pour créer de petits modules individuels, dont la liste incombe aux programmeurs, que d'essayer, à l'esprit, d'estimer le calendrier de développement de l'ensemble du projet.

Si plusieurs programmeurs participent à un grand projet (comme cela arrive généralement), alors la présence d'un plan pré-développé, un certain document, facilitera grandement leur interaction les uns avec les autres. En fait, diverses tâches formulées dans ce document peuvent être attribuées à des développeurs individuels. Sa présence aidera les membres de l'équipe à être conscients de ce que font leurs collègues.

Et enfin, grâce à ce document, vous pouvez voir très clairement comment les travaux sur le projet avancent. Les programmeurs passent souvent du travail sur une partie de l'application à une autre et reviennent à ce qu'ils ont fait auparavant, bien plus tard qu'ils ne le souhaiteraient.
Considérez le processus de planification des applications.

▍Étape 1: pages et composants


Il est nécessaire de déterminer l'apparence et la fonctionnalité de chaque page de l'application. L'une des meilleures approches consiste à dessiner chaque page. Vous pouvez le faire à l'aide de l' outil de maquette ou manuellement sur papier. Cela vous donnera une bonne compréhension des informations qui doivent être présentes sur chaque page. Voici à quoi pourrait ressembler une mise en page.


Mise en page (prise à partir d'ici )

Dans la disposition ci-dessus, vous pouvez facilement identifier les entités de conteneur parent et leurs enfants. Plus tard, les conteneurs parents deviendront les pages de l'application et des éléments plus petits tomberont dans le dossier des components du projet. Une fois les mises en page de dessin terminées, écrivez sur chacune d'elles le nom des pages et des composants.

▍Étape 2: actions et événements


Après avoir décidé des composants de l'application, réfléchissez aux actions qui seront exécutées dans chacun d'eux. Plus tard, à partir de ces composants, ces actions seront envoyées.

Considérez une boutique en ligne sur la page d'accueil qui affiche une liste de produits recommandés. Chacun des éléments de cette liste sera présenté dans le projet en tant que composante distincte. Laissez le nom de ce composant être ListItem .


Un exemple de page d'accueil de boutique en ligne (prise à partir d'ici )

Dans cette application, l'action que le composant de la section Product prend est appelée getItems . Certaines autres activités qui peuvent être incluses sur cette page peuvent inclure getUserDetails , getSearchResults , etc.

▍Étape 3: données et modèles


Certaines données sont associées à chaque composant de l'application. Si les mêmes données sont utilisées par plusieurs composants d'application, elles feront alors partie d'une arborescence d'état centralisée. L'arbre d'état est géré à l'aide de Redux .

Ces données sont utilisées par de nombreux composants. Par conséquent, lorsque les données sont modifiées par un composant, elles se reflètent dans d'autres composants.

Créez une liste de données similaires pour votre application. Il deviendra un modèle de diagramme. Sur la base de cette liste, il sera possible de créer des réducteurs.

 products: {  productId: {productId, productName, category, image, price},  productId: {productId, productName, category, image, price},  productId: {productId, productName, category, image, price}, } 

Revenons à l'exemple ci-dessus avec une boutique en ligne. La section des produits recommandés et des nouveaux produits utilise le même type de données que celui utilisé pour représenter les produits individuels (quelque chose comme un product ). Ce type servira de base pour créer l'un des réducteurs d'application.

Après avoir documenté le plan d'action, il est temps de considérer certains des détails nécessaires pour configurer la couche d'application chargée de travailler avec les données.

Actions, sources de données et API


Au fur et à mesure que votre application se développe, il arrive souvent qu'un nombre excessif de méthodes soient associées au référentiel Redux. Il arrive que la structure du répertoire s'aggrave, s'écartant des besoins réels de l'application. Tout cela devient difficile à maintenir, l'ajout de nouvelles fonctionnalités à l'application devient plus compliqué.

Parlons de la façon dont vous pouvez ajuster certaines choses afin de garder le code du référentiel Redux propre à long terme. De nombreux problèmes peuvent être évités si, dès le début, les modules sont conçus pour être réutilisables. Cela vaut la peine de faire exactement cela, même si au début cela peut sembler un excès, compliquant inutilement le projet.

▍ Conception d'API et applications clientes


Lors de la configuration initiale du référentiel, le format des données provenant de l'API affecte considérablement la structure du référentiel. Souvent, les données doivent être converties avant de pouvoir être transférées vers des réducteurs.

Récemment, beaucoup a été dit sur ce qui est nécessaire et ce qui ne doit pas être fait lors de la conception d'une API. Des facteurs tels que le cadre principal et la taille de l'application ont un impact supplémentaire sur la conception des API.

Il est recommandé, comme dans le développement d'applications serveur, de stocker les fonctions auxiliaires dans un dossier séparé. Il peut s'agir, par exemple, de fonctions de formatage et de mappage de données. Assurez-vous que ces fonctions n'ont pas d'effets secondaires (voir cet article sur les fonctions pures).

 export function formatTweet (tweet, author, authedUser, parentTweet) {  const { id, likes, replies, text, timestamp } = tweet  const { name, avatarURL } = author  return {    name,    id,    timestamp,    text,    avatar: avatarURL,    likes: likes.length,    replies: replies.length,    hasLiked: likes.includes(authedUser),    parent: !parentTweet ? null : {      author: parentTweet.author,      id: parentTweet.id,    } 

Dans cet exemple de code, la fonction formatTweet ajoute une nouvelle clé ( parent ) à l'objet tweet de l'application frontale. Cette fonction renvoie des données en fonction des paramètres qui lui sont transmis, sans affecter les données extérieures.

Ici, vous pouvez aller encore plus loin en mappant des données à un objet décrit précédemment dont la structure correspond aux besoins de votre application frontale. Cependant, vous pouvez valider certaines clés.

Parlons maintenant des parties des applications qui sont responsables des appels à l' API .

▍ Organisation du travail avec les sources de données


Ce dont nous parlerons dans cette section sera directement utilisé par Redux pour modifier l'état de l'application. En fonction de la taille de l'application (et, en outre, du temps dont dispose le programmeur), vous pouvez aborder la conception de l'entrepôt de données en utilisant l'une des deux approches suivantes:

  • Sans recours à un agent (coursier).
  • Utilisation de l'agent.

▍ Concevoir un référentiel sans utiliser d'agent


Avec cette approche, lors de la configuration du stockage, les mécanismes d'exécution des requêtes GET , POST et PUT pour chaque modèle sont créés séparément.


Les composants interagissent avec l'API sans utiliser d'agent

Le diagramme précédent montre que chaque composant envoie des actions qui appellent des méthodes de différents magasins de données. Voici à quoi ressemblera, avec cette approche, la méthode BlogApi fichier BlogApi :

 function updateBlog(blog){   let blog_object = new BlogModel(blog)   axios.put('/blog', { ...blog_object })  .then(function (response) {    console.log(response);  })  .catch(function (error) {    console.log(error);  }); } 

Cette approche fait gagner du temps ... Et au début, elle vous permet également d'apporter des modifications au code sans vous soucier des effets secondaires. Mais à cause de cela, le projet aura une grande quantité de code redondant. De plus, l'exécution d'opérations sur des groupes d'objets nécessitera beaucoup de temps.

▍ Conception d'un référentiel à l'aide d'un agent


Avec cette approche, à long terme, le projet est plus facile à maintenir, il est plus facile de faire des changements. La base de code ne devient pas polluée au fil du temps, car le développeur est épargné par le problème de l'exécution de requêtes parallèles à l'aide d'axios.


Les composants interagissent avec l'API à l'aide d'un agent

Cependant, avec cette approche, un certain temps est nécessaire pour la configuration initiale du système. Elle est moins flexible. C'est à la fois bon et mauvais, car cela ne permet pas au développeur de faire quelque chose d'inhabituel.

 export default function courier(query, payload) {   let path = `${SITE_URL}`;   path += `/${query.model}`;   if (query.id) path += `/${query.id}`;   if (query.url) path += `/${query.url}`;   if (query.var) path += `?${QueryString.stringify(query.var)}`;     return axios({ url: path, ...payload })     .then(response => response)     .catch(error => ({ error })); } 

Le code de la méthode de courier base est courier . Tous les gestionnaires d'API peuvent l'appeler en lui transmettant les données suivantes:

  • Demander un objet contenant des informations liées à l'URL. Par exemple, le nom du modèle, la chaîne de requête, etc.
  • La charge utile contenant les en-têtes de demande et son corps.

▍ Appels API et actions internes de l'application


Lorsque vous travaillez avec Redux, une attention particulière est accordée à l'utilisation d'actions prédéfinies. Cela rend les changements de données survenant dans l'application prévisibles.

Définir un tas de constantes dans une grande application peut sembler une tâche impossible. Cependant, la mise en œuvre de cette tâche est grandement simplifiée grâce à la phase de planification que nous avons examinée précédemment.

 export const BOOK_ACTIONS = {   GET:'GET_BOOK',   LIST:'GET_BOOKS',   POST:'POST_BOOK',   UPDATE:'UPDATE_BOOK',   DELETE:'DELETE_BOOK', } export function createBook(book) {   return {      type: BOOK_ACTIONS.POST,   book  } export function handleCreateBook (book) {   return (dispatch) => {      return createBookAPI(book)         .then(() => {            dispatch(createBook(book))         })         .catch((e) => {            console.warn('error in creating book', e);            alert('Error Creating book')         })  } export default {   handleCreateBook, } 

L'extrait de code ci-dessus montre un moyen simple d'utiliser les méthodes de source de données createBookApi avec des actions Redux. La méthode createBook peut facilement être transmise à la méthode de dispatch Redux.

En outre, notez que ce code est stocké dans le dossier dans lequel les fichiers d'action du projet sont stockés. De même, vous pouvez créer des fichiers JavaScript qui déclarent des actions et des gestionnaires pour d'autres modèles d'application.

Résumé


Aujourd'hui, nous avons parlé du rôle de la phase de planification dans le développement de projets à grande échelle. Nous avons également discuté ici des caractéristiques de l'organisation de l'application avec les sources de données. La prochaine partie de cet article se concentrera sur la gestion de l'état d'une application et le développement d'une interface utilisateur évolutive.

Chers lecteurs! Où commencez-vous à développer des applications React?

Source: https://habr.com/ru/post/fr458496/


All Articles