Je suis nouveau dans le monde des réactions et dans le monde du fullstack dans son ensemble, mais j'ai cherché sans cesse une réponse à ce qui suit et quelques conseils seraient vraiment appréciés.
Je crée une application avec React et Express. Cela nécessite une authentification, donc je prévoyais d'utiliser Passport pour vous aider. Le JS côté client utilise des routeurs React pour naviguer sur le site Web. Tout va bien, mais mon problème concerne la demande initiale GET effectuée par le navigateur.
Je vais d'abord décrire les exigences spécifiques de mon application, puis généraliser ce que je ne comprends pas.
Comme je l'ai dit, mon application nécessite une authentification OAuth2. Si vous essayez d'obtenir un chemin sur mon site Web et que vous n'êtes pas connecté, il devrait simplement charger la page de connexion. Si vous êtes connecté, chargez normalement et trouvez votre chemin. Semblable à Facebook, j'aimerais que l'URL de connexion soit la même que la page "flux". Si similaire à la façon dont la route facebook.com '/' est soit la page de connexion, soit votre nouveau flux selon que vous êtes connecté, je veux la même chose.
D'après ce que j'ai compris, Passport s'authentifie sur le back-end en vérifiant l'en-tête de la demande. Je comprends donc que je devrais avoir une sorte de middleware qui dit "si l'utilisateur est connecté, continuez sur les routes sinon affichez la page de connexion" ... Comment est-ce fait? À quoi ressemblerait le code? Ma seule expérience avec Express provenait d'une classe d'introduction qui utilisait res.render pour renvoyer un fichier HTML et le transmettre à un moteur de modèle comme les guidons. Mais je n'ai aucune idée de comment cela fonctionnerait avec les routes de réaction. Est-ce que j'utiliserais toujours res.render ()? Autre chose?
Disons que mon index.html a la racine div dans laquelle injecter la réaction. Si je devais deviner, je renverrais cette page index.html avec le fichier .js avec les routes et, d'une manière ou d'une autre, sur le backend, je renverrais la route que je veux qu'elle corresponde sur mes routes de réaction (soit celle de connexion, soit l'utilisateur demandé) ??
Plus généralement, je suppose que je ne sais pas comment la requête initiale à un site Web utilisant des routes de réaction est effectuée. 1) Comment le serveur interagit-il avec tout pour rendre ce que j'ai demandé? 2) À quoi ressemblerait le code pour cela. Ma seule expérience avec React provient d'un cours de base Udemy qui a juste utilisé "react-scripts start" pour afficher la page.
Après avoir passé toute la journée à googler cette question, cela m'a conduit à SSR qui est un terrier de lapin en soi et je ne sais même pas si c'est ce dont j'ai besoin pour m'aider. Vraiment?
Il me manque clairement des connaissances fondamentales car cela me trébuche vraiment, donc si vous avez des ressources pour en savoir plus, publiez-les simplement. Merci!
3 Réponses :
Je pense que l'écart fondamental avec lequel vous vous débattez provient du fait que beaucoup de ces `` cours d'introduction '' poussent l'ensemble du client du navigateur dans le serveur d'applications pour que les choses soient rapidement opérationnelles, car le serveur Node rend l'ensemble de React app AND fonctionne comme une API ...
// Ajax request from React app to: http://example.com/api app.use('/api/*'),()=> { res.send({ <!-- some JSON object -->}) }) // User visits in browser: http://example.com/**/* app.use('/*',()=>{ res.render(<!-- entire React App sent to browser -->) })
La première requête (en supposant que l'utilisateur ne visite pas / api / *) enverra simplement le bundle React. Une navigation supplémentaire de l'utilisateur dans le client enverrait généralement des requêtes XHR (ou ouvrirait des WebSockets) depuis l'application React vers des routes Express s'exécutant sur le même programme de nœud.
Dans de nombreuses situations, il est logique de séparer ces parties de votre programme, par exemple en ayant réagi depuis un emplacement complètement différent de celui où il demande des données. Il y a de nombreuses raisons à cela, mais l'optimisation des ressources informatiques en fonction de leurs différentes demandes de CPU, de mémoire, de réseau .etc et de la gérabilité du code / du déploiement sont les principales raisons pour moi.
Par exemple ...
Visites des utilisateurs: http://example.com *
Réagissez en gros à la fonctionnalité native de «localisation» du navigateur (ce qui est affiché après votre nom de domaine). Ainsi, tous les événements après le chargement initial de la page (clics sur les boutons et autres) sont entièrement gérés par React en interne et utilisent ces itinéraires pour déterminer ce qu'il faut afficher ou quelles données récupérer de l'API via Ajax (XHR). Si l'utilisateur effectue un rechargement dur de la page, cette demande reviendra au serveur et il recommencera tout le cycle Réagir le routeur Autorise vous faire 2 choses simultanément ... Je n'ai joué qu'avec SSR pour pouvoir lui parler, mais il offre une latence extrêmement faible pour les rendus initiaux, en le faisant en 1 requête réseau, vous voulez donc l'utiliser dans les zones de votre programme où cela est important. Je ne sais pas si cela répond à votre question, mais faites-moi savoir si vous souhaitez que je développe quelque chose ou que j'en donne plus ressources détaillées.
Merci! Dans votre premier exemple de code, vous supposez que le «point d'entrée» dans le navigateur est la route «/». Mais cela peut être n'importe quelle page de mon site Web. Auriez-vous besoin d'un app.get () pour toutes les routes - si l'utilisateur a fait example.com/about
En ce qui concerne votre deuxième exemple, je comprends que les appels suivants seraient des appels AJAX puisque j'utiliserais des routes de réaction pour la navigation interne. La confusion principale est avec le rendu initial de la page via le navigateur. Comment dans le backend, si un utilisateur demande une page / about, puis-je le rediriger vers la page de connexion '/'
PS: Mon premier exemple était juste un pseudo-code, mais je me rends compte que c'est déroutant si vous comprenez le routage Express. Je l'ai changé pour qu'il soit réellement fonctionnel maintenant, comme dans, chaque structure de requête à l'exception de / api / * sera dirigée directement vers React, mais vous pouvez également voir pourquoi cela peut être inefficace / dangereux. Vos utilisateurs peuvent désormais interroger accidentellement votre API. Je sers beaucoup de mes API à partir d'un sous-domaine comme "api.example.com", donc il y a une séparation claire des préoccupations.
Et je viens de mettre à jour ma solution pour répondre à votre question car je pense que c'est une partie importante de ce que vous demandiez.
Est-ce que je peux vous aider avec autre chose Sinon, et vous avez trouvé que c'était la réponse la plus appropriée, cela me dérangerait de marquer cette réponse comme `` acceptée '' afin que j'obtienne cette jolie coche verte :)
Je comprends votre combat car j'ai dû le traverser moi-même en combinant front-end et back-end, en particulier React et Node. Donc, tout d'abord, nous savons que le navigateur / client lancera toujours une requête au serveur, alors comment React Router prend-il le contrôle des routes? Eh bien, c'est simple en fait, tout ce que vous avez à faire est de renvoyer l'intégralité de l'application de réaction depuis n'importe quel itinéraire depuis votre serveur express. Le code ressemblera à ceci:
app.get('/api/v1/*', (req, res, next) { // Return some data in json format });
Une fois que l'application react s'affiche sur le navigateur de l'utilisateur (ne vous inquiétez pas des chemins, car react sera automatiquement rendu en fonction de l'URL en fonction du code que vous écrit côté client, il se chargera également de l'authentification par rapport à la page de flux lorsqu'il analysera votre stockage local, les cookies, etc.), il prendra le contrôle du routage, au lieu d'une requête allant au serveur express. Mais que se passe-t-il lorsque nous demandons des données à notre serveur, eh bien, cela renvoie l'application react sur chaque route, nous devons donc configurer une route api pour gérer toutes les demandes de données.
const express = require('express'); const app = express(); app.get('/*', (req, res, next) => { // Return React App index.html }); app.listen(3000);
Espérons que, cela vous donne un aperçu de ce que vous recherchiez.
Merci! D'après ce que je comprends, nous renvoyons simplement la page index.html (la page racine avec le
Désolé, manque d'espace - Avez-vous des conseils sur la façon de résoudre ce problème? Comment renvoyer index.html s'il se trouve dans un référentiel différent?
Salut, vous l'avez bien compris. De plus, la plupart des projets sont abordés comme le vôtre, front-end et back-end sont séparés les uns des autres. Habituellement, lors du test de votre application, vous exécutez l'application react sur le serveur de développement webpack et l'application express sur le serveur de nœuds (qui sont indépendants les uns des autres). En production, ce n'est pas le cas, votre application express doit connaître l'emplacement des fichiers côté client, qui est défini par app.use (express.static (__ dirname + './..front-end/dist/ '));
(généralement / dist est le répertoire dans lequel vos fichiers frontaux sont intégrés et contient des scripts html ico etc).
Cela peut vous aider à clarifier un peu plus votre point de vue: medium.com/front-end-weekly/...
SSR est un peu déroutant pour les développeurs qui ont moins d'expérience, oublions-le pour l'instant.
Il vous sera plus facile de supposer que le JavaScript frontend (React) et le Javascript backend (NodeJS) sont deux applications distinctes , et ils communiquent entre eux via l'API.
voici le code qui montre le composant Login et le composant Feed selon que vous êtes connecté ou non p>
const express = require("express"); const app = express(); app.get('/api/feeds', (req, res, ) => { const feeds = [ {}, {} ] res.status(200).json(feeds); }); app.listen(3001);
et ceci est votre backend
import React, { Component } from "react"; import axios from "axios"; class Home extends Component { constructor() { const accessToken = localStorage.getItem("accessToken"); this.state = { accessToken, feeds: [] }; } componentDidMount() { if (this.state.accessToken) { axios(`api/feeds?accessToken=${this.state.accessToken}`).then(({ data }) => { this.setState({ feeds: data }); }); } } render() { if (this.state.accessToken) { return <FeedsComponent feeds={this.state.feeds} />; } return <LoginComponent />; } }
gardez simplement à l'esprit qu'il s'agit de deux applications distinctes, elles peuvent être dans deux dossier, serveur différent, port différent.