Les sites Web de BBC World Service News sont rendus à l'aide de Simorgh, une application basée sur ReactJS. Simorgh rend également les pages d'articles de presse AMP pour le service mondial, les nouvelles de la fonction publique et la BBC Sport.
Simorgh offre une expérience Web rapide et accessible utilisée par des millions de personnes dans le monde chaque mois (voir la liste des sites Web utilisant Simorgh). Il est régulièrement entretenu et bien documenté, et nous accueillons des contributeurs open source.
Simorgh est principalement maintenu par les équipes de BBC News Web Engineering. Il fournit des nouvelles très fiables aux lecteurs du monde entier, actuellement en (41 langues). Nous prenons en charge un large éventail d'appareils et nous nous soucions profondément de l'échelle, des performances et de l'accessibilité. Nous travaillons dans des équipes agiles et flexibles et avons une feuille de route passionnante pour le développement futur.
Veuillez vous familiariser avec notre:
NB Il y a une documentation supplémentaire colocalisée avec du code pertinent. La liste ci-dessus est un index de la documentation de niveau supérieur de notre dépôt.
Une demande à un article de la BBC (https://www.bbc.co.uk/news/articles/clldg965yzjo) est transmise à l'application Simorgh à partir d'un service de routage et de mise en cache propriétaire (appelé Mozart).
La demande correspond à un itinéraire dans notre serveur express en utilisant une correspondance regex ( articleRegexPath || frontPageRegexPath ). Si l'URL correspond au modèle regex prédéfini pour un article ou une première page, nous récupérons certains paramètres de l'itinéraire à l'aide de la fonction getRouteProps . Cela renvoie les propriétés du service, de l'isamp, de l'itinéraire et de la correspondance. La route est un itinéraire React-Router qui définit une méthode pour récupérer le JSON initial utilisé pour rendre la page et le conteneur réactif dans lequel rendre IE ArticleContainer , cela s'appelle généralement getInitialData
Une fois les données renvoyées, nous tirons le code d'état et transmettons toutes ces données sous forme d'accessoires à notre document principal à l'aide de renderDocument .
Le document passe l'URL, les données JSON, l'origine BBC, l'ISAMP et le service au conteneur d'application principal et le résultat est rendu à une chaîne à l'aide de la méthode renderToString . Cette chaîne est ensuite transmise à DocumentComponent en tant qu'application principale avec le tableau des actifs, les balises de style (la sortie des composants stylisés) et tous les scripts / liens qui doivent être ajoutés à la tête. Ceci est ensuite rendu au balisage HTML statique à l'aide de réactions propre renderToStaticMarkup et renvoyé à l'utilisateur en tant que HTML statique. Cette réponse comprend des liens vers nos groupes JS qu'un appareil utilisateur téléchargera pour bootstrap l'application (SPA) pour une seule page pour les voyages ultérieurs.
Maintenant que le HTML brut a été téléchargé, le fichier JS côté client entre en jeu et hydrate la réponse initiale avec l'application côté client. Au cours de ce processus, React utilise la charge utile JSON initiale (disponible sur l'objet de fenêtre global SIMORGH_DATA ) pour hydrater le balisage d'origine renvoyé par ReactDomServer. React s'attend à ce que le contenu rendu est identique entre le serveur et le client (c'est pourquoi nous envoyons la charge utile JSON initiale avec la page SSR, de sorte que la phase d'hydratation s'exécute avec les mêmes données que le rendu du serveur est utilisé).
La charge utile JSON pour un article se compose d'un certain nombre de blocs. Chaque bloc est un objet qui représente un élément sur la page, il peut s'agir d'un titre, d'une image, d'un paragraphe, etc. Chacun de ces blocs a un type de bloc et un type de bloc correspondra à un conteneur spécifique dans Simorgh EG BlockType: l'image correspondra au conteneur d'image.
Le conteneur articlemain itérera sur chaque bloc JSON, le correspondra à son conteneur réactif correspondant et passera les données via des accessoires. Ces conteneurs sont l'endroit où se trouve la logique pour rendre chaque type de bloc. C'est à ce stade que nous utilisons les composants de frontend installés de la bibliothèque de composants PSAmead. Par exemple, le conteneur d'image importera le conteneur de figure et la figure importe et utilisera les composants PsamEad-Image et les composants PsamEad-Image-Placeholder. Une image sur un article aura généralement une légende, de sorte que le conteneur de figure importera le conteneur de légende qui peut inclure plus de composants frontaux de Psamadead pour rendre une légende sur l'image.
Ce processus est répété pour chaque bloc au sein d'un article, ce qui rend finalement le corps principal d'un article de presse en utilisant une combinaison de conteneurs React pour la logique métier et les composants React pour le balisage du frontend.
Chaque rendu est passé par un ensemble de HOC (composants d'ordre supérieur) pour améliorer la page, ces hoc sont;
Avec une sélection de types de pages passés par WithOptizelyProvider, cela permet d'utiliser Optimizely dans les types de pages sélectionnés.
La variante HOC garantit que les services qui ont des variantes (par exemple simp , lat ) redirigent toujours vers une URL qui rend la variante appropriée.
Si un utilisateur navigue vers une URL sans fournir la variante et que la variante est définie dans Cookie, la page de variante cookie est rendue. Sinon, la page de variante par défaut est rendue
Si un utilisateur navigue vers une URL avec une variante et que la variante est définie dans Cookie, la page de variante cookie est rendue. Sinon, la page variante demandée est rendue.
Le WithContexts HOC est un emballage qui donne accès aux différents fournisseurs de contexte disponibles dans l'application. Tout composant enfant à l'intérieur de ces fournisseurs de contexte a accès aux données de contexte via le crochet UseContexts.
Le wrapper hoc en termes de conteneurs d'article ou de page frontal avec une mise en page, à l'heure actuelle, nous n'avons qu'une seule mise en page. Cette disposition comprend l'en-tête, le pied de page et les fournisseurs de contexte rendant le corps principal en tant qu'enfant entre l'en-tête et le pied de page.
L'erreur HOC vérifie la proportion d'erreur transmise, si l'erreur est définie sur null l'article ou le conteneur de page Frontpage est simplement renvoyé.
Si l'erreur est définie sur true, le composant d'erreur est renvoyé, donnant à l'utilisateur une indication visuelle de l'erreur, par exemple une page d'erreur de 500.
En supposant que les autres HOC ont renvoyé l'article d'origine ou le conteneur FrontPage, les données HOC effectueront des vérifications de validation sur les données JSON transmises via le conduit de données. Si tous les chèques sont satisfaits, le contracteur en état est retourné avec un seul accessoire pageData . Ces accessoires Pagedata abriteront les données JSON à rendre par exemple les blocs Optimo pour un article donné.
Le HOC HOCHANGHANGEHANDLER est un wrapper appliqué à toutes les pages qui vérifient les modifications de la valeur de hachage URL. Les pages incluent des contrôles d'accessibilité pour sauter le contenu si l'utilisateur choisit de le faire, cela utilise le hachage URL pour sauter les utilisateurs vers des zones spécifiques de la page. En raison de la nature du routage côté client, les modifications de l'URL se traduisent par un rendement. Cela provoque un scintillement d'interface utilisateur disgracieux pour certains composants, en particulier les médias et les intégres sociales. Ce HOC applique des vérifications à l'URL, alors voyez si une reprise est nécessaire, ou si vous ne prévenez pas une réendettement à l'aide de React.memo .
Le WithOptizelyProvider HOC renvoie des composants qui ont été améliorés avec l'accès à un client Optimizely, qui est utilisé pour exécuter nos tests A / B. Ceci est fait pour limiter les tailles de faisceaux, car nous séparons certains de nos faisceaux par type de page, cela signifie que si nous effectuons uniquement des tests A / B sur certains types de pages, nous pouvons empêcher les faisceaux de type de page polluants avec le poids de la bibliothèque SDK que nous utilisons pour Optimizelly.
WithOptimizelyProvider doit être ajouté car la valeur de la clé d'objet handlerBeforeContexts dans ApplyBasicPageHandlers.js, car le ckns_mvt est défini dans l'USERCONText, de sorte que le hoc withOptimizelyProvider doit être appliqué dans le bon ordre le long du HOC WithOptizelyProvider. Cela rend le ckns_mvt disponible lors des premières visites pour passer dans l' OptimizelyProvider , ainsi que des attributs tels que service , qui est utilisé pour déterminer quand Optimizely devrait activer une expérience.
Exemple de la page de l'article:
import withOptimizelyProvider from '#app/legacy/containers/PageHandlers/withOptimizelyProvider' ;
import ArticlePage from './ArticlePage' ;
import applyBasicPageHandlers from '../utils/applyBasicPageHandlers' ;
export default applyBasicPageHandlers ( ArticlePage , {
handlerBeforeContexts : withOptimizelyProvider ,
} ) ;Lors de l'ajout d'un nouveau type de page, plusieurs pièces sont nécessaires.
/data/{{service}}/{{pageType}}/.jsonlocalhost:7080/igbo.json devrait avoir les données pour créer la page d'index localhost:7080/igbomain avec un flex-grow: 1; Déclaration de CSS, c'est pour s'assurer qu'elle se développe pour remplir l'espace entre l'en-tête visuel et le pied de page, la div root en utilisant une implémentation flexible `` footter sticky ''. cypress/support/config/settings.js pour chaque service (même si pour définir le nouveau type de page sur indéfini)cypress/integration/pages/cypress/integration/pages/ Vous devez vous assurer que les pipelines E2E sont mis à jour pour exécuter le nouveau pipeline E2E E2E E2e Test et Live E2ENB: Avec autant d'étapes, il est suggéré d'avoir plusieurs PR lors de l'ajout d'un nouveau type de page pour ne pas avoir de PR énorme singulière. Cependant, si les tests de cyprès (# 6) ne sont pas ajoutés dans le même PR que le routage de la page (# 5), ils doivent immédiatement suivre le Roiting PR de la page, idéalement, ceux-ci devraient être gérés dans un seul PR.
Veuillez lire: contribution.md
Installez le nœud. https://nodejs.org/en/. Nous utilisons la version spécifiée dans .nvmrc et si vous avez un Node Version Manager (NVM), vous pouvez exécuter le script suivant pour passer automatiquement à la version prise en charge du projet.
nvm use
Le projet Simorgh utilise le fil pour la gestion des packages. Il est recommandé d'installer du fil via le gestionnaire de package NPM, qui est livré avec Node.js lorsque vous l'installez sur votre système. Pour installer le fil, exécutez cette commande:
npm install --global yarn
Ensuite, vous pouvez exécuter les commandes suivantes pour installer Simorgh
git clone [email protected]:bbc/simorgh.git
cd simorgh
yarn install
Pour exécuter cette application localement, avec un montage à chaud, exécutez
yarn dev
L'application commencera sur http: // localhost: 7080.
Les pages d'articles sont servies sur les routes du format /news/articles/:id où ID est l'ID d'actif généré par le système de gestion de contenu.
FYI: Article expliquant l'utilisation par la BBC des ID dans URL
Ces deux articles de presse sont disponibles sur l'environnement de test de notre CMS, ainsi que localement, ils sont donc souvent utilisés pour les tests:
Nous servons également des pages HTML AMP à la route /news/articles/:id.amp https://www.amproject.org
Les services avec des variantes ne sont pas accessibles en utilisant le format ci-dessus, mais la variante doit être fournie dans l'URL.
Les premières pages du service mondial sont servies dans le format /:service où service représente un site de service mondial:
Les premières pages du World Service suivent également le format de l'article pour AMP, étant disponible sur /:service.amp :
Les services avec des variantes ne sont pas accessibles en utilisant le format ci-dessus, mais la variante doit être fournie dans l'URL.
Les pages de sujets utilisent des API BBC internes qui ne sont pas accessibles au public. Cela peut faire apparaître les avertissements suivants lors du développement localement:
No BFF_PATH set as environment variable, you will not have access to topics
Les développeurs internes qui ont besoin de travailler sur les pages de sujets localement doivent contacter l'équipe pour l'accès.
Les recommandations dans les pages d'histoire utilisent également les API internes de BBC Data Labs. Il nécessite d'ajouter la paire de touches / valeur dans le fichier envConfig/secret.env pour qu'ils apparaissent localement.
Les développeurs internes qui ont besoin de travailler sur les pages d'articles localement doivent contacter l'équipe pour l'accès.
Vous pouvez trouver d'autres types de pages en parcourant nos itinéraires et leurs associés regex, mais nous vous suggérons de commencer par ce qui précède, puis jetez un œil au cœur de l'application pour comprendre et trouver les autres itinéraires.
Nous utilisons un livre de contes pour développer des composants isolément de l'application Simorgh. Vous pouvez y accéder sur https://bbc.github.io/simorgh/
Pour exécuter yarn storybook localement, il sera alors disponible sur http: // localhost: 9001 /. L'introduction et la documentation pour le livre de contes sont ici: https://storybook.js.org/basics/introduction/.
Lorsque vous consultez les histoires vidéo localement, assurez-vous d'utiliser un domaine BBC, comme indiqué dans la section de l'emplacement de la demande de changement. La vidéo ne fonctionnera pas dans la version hébergée du livre de contes lié ci-dessus pour cette raison.
Nous utilisons également une QA chromatique pour exécuter des tests de navigateur croisé sur nos histoires.
Veuillez également noter que si vous souhaitez voir les composants rendus avec nos polices, vous devrez forcer une repection de la toile. En effet, nos polices ont toutes la propriété de font-display optional ou swap conformément aux stratégies de chargement respectives ici: https://ws-downloads.files.bbci.co.uk/fonts/index.html. Le moyen le plus simple de forcer une repeinte est simplement de déplacer le séparateur entre la fenêtre d'aperçu dans la section et Knobs ou de redimensionner la fenêtre du navigateur.
Si vous souhaitez héberger l'application pour être accessible via votre réseau local, suivez les instructions ici.
Pour exécuter cette application localement avec une construction de production, exécutez: yarn build && yarn start .
Nous utilisons yarn build localement qui regroupe l'application pointant vers LocalHost pour les données et les actifs statiques.
Ceci est principalement utilisé pour déboguer latest en utilisant les faisceaux de test et d'environnement en direct. Assurez-vous que les faisceaux existent dans l'emplacement de l'actif statique pour l'environnement correct avant de commencer à déboguer.
Pour exécuter des bundles de test sur localhost:
envConfig/test.env modifie les valeurs de:LOG_DIR='/var/log/simorgh' à LOG_DIR='log'rm -rf build && yarn build:test && yarn startPour exécuter des paquets en direct sur localhost:
envConfig/live.env modifiez les valeurs de:LOG_DIR='/var/log/simorgh' à LOG_DIR='log'rm -rf build && yarn build:live && yarn startCertaines fonctionnalités fonctionnent différemment en fonction du fait qu'un utilisateur est situé au Royaume-Uni ou à l'étranger. Vous pouvez demander explicitement une version spécifique en accédant à Simorgh via un domaine BBC localhost spécifique:
Si ces URL ne fonctionnent pas, vous devrez peut-être ajouter une entrée de fichier d'hôtes ( /etc/hosts ou C:WindowsSystem32driversetchosts ):
127.0.0.1 localhost.bbc.co.uk
127.0.0.1 localhost.bbc.com
Sur le déploiement, make buildCi est exécuté dans l'environnement CI qui crée des faisceaux pour les environnements test et live . Sur les deux environnements, les fichiers .env.test ou .env.live écrasent le fichier .env qui est utilisé pour exécuter l'application avec les bundles corrects.
Chaque exécution de yarn build mettra à jour les fichiers d'analyse du bundle dans le dépôt. Pour afficher une ventilation de la taille du bundle, ouvrez le rapport HTML généré dans un navigateur ./reports/webpackBundleReport.html Ceci est généré via webpack-bundle-analyzer . Les données sont également disponibles en JSON ./reports/webpackBundleReport.json .
Nous avons lié avec le style Airbnb et nous utilisons plus jolis comme formateur de code. Ils peuvent être exécutés avec yarn test:lint .
Nous avons des tests d'unité de plaisanterie qui peuvent être exécutés avec yarn test:unit .
yarn test exécute les deux ensembles de ceux-ci.
Nous utilisons Cypress pour nos tests de bout en bout. Pour exécuter les tests de fumée localement, exécutez cette commande unique:
yarn test:e2e
Il fera tourner un serveur de production sur le port 7080 et exécutera les tests Cypress contre cela. Pour exécuter les tests de fumée de manière interactive, exécutez:
yarn test:e2e:interactive
Cela charge une interface utilisateur qui permet facilement d'exécuter des tests individuels à côté d'un flux visuel du navigateur, au fil des tests.
Il existe plusieurs variables d'environnement que vous pouvez utiliser avec notre suite de tests, qui sont:
| Variable d'environnement | Effet | Valeurs possibles |
|---|---|---|
| Cypress_only_service | Restreint à l'exécution uniquement du service spécifié | Un seul service, c'est-à-dire CYPRESS_ONLY_SERVICE=urdu |
| Cypress_app_env | Exécute les tests dans un environnement spécifique | test , local , live |
| Cypress_smoke | Ne fait que des tests de fumée si cela est vrai | true , false |
| Cypress_uk | Voir Running E2ES au Royaume-Uni contre Live | true , false |
| Cypress_skip_eu | Voir Running E2ES en dehors de l'UE | true , false |
Ces commandes peuvent être exécutées en combinaison.
La façon par défaut d'exécuter la suite E2E AKA yarn test:e2e ou yarn test:e2e:interactive exécute un sous-ensemble de nos tests, autrement connu sous le nom de tests de fumée . Pour exécuter la suite complète:
CYPRESS_SMOKE=false yarn test:e2e
Les tests peuvent être limités à exécuter uniquement pour un seul service en le spécifiant à l'aide de la variable d'environnement CYPRESS_ONLY_SERVICE . Par exemple:
CYPRESS_ONLY_SERVICE=urdu yarn test:e2e
Pour exécuter uniquement une spécification particulière, il est nécessaire d'invoquer directement Cypress. Assurez-vous d'abord que Simorgh s'exécute déjà dans un autre onglet, puis exécutez (par exemple, pour exécuter uniquement les tests d'articles):
npx cypress run --spec cypress/integration/pages/articles/index.js
De plus amples détails sur l'utilisation de la CYPRI sont disponibles sur https://docs.cypress.io/guides/guides/command-line.html
Cela affecte les développeurs basés uniquement au Royaume-Uni (mais peut vous affecter si vous utilisez un routage VPN via le Royaume-Uni)
La fonction Cypress .Visit () est verrouillée pour visiter un seul domaine par test. Cela devient problématique lorsque vous lancez les tests E2E à partir du Royaume-Uni, en raison des redirections de .com vers .co.uk . Par défaut, les tests de Cypress fonctionneront comme s'ils étaient exécutés en dehors du Royaume-Uni. Afin d'exécuter ces tests du Royaume-Uni, vous devez passer dans la variable UK Cypress Environment aux tests. Cela remplacera les terminaisons URL en .co.uk , ce qui vous permettra d'exécuter ces tests avec succès.
Voici un exemple de commande:
CYPRESS_APP_ENV=test CYPRESS_UK=true CYPRESS_SMOKE=true yarn cypress
Cela affecte les développeurs basés à partir de l'UE (mais peut vous affecter si vous utilisez un routage VPN à travers un pays non dans l'UE)
L'exécution de tests de cyprès en dehors de l'UE ne montrera pas les bannières de consentement de l'UE sur AMP, ce qui peut entraîner l'échec de certains tests. Définissez CYPRESS_SKIP_EU=true pour empêcher ces tests d'exécuter en dehors de l'UE.
Un exemple de commande sera:
CYPRESS_SKIP_EU=true yarn cypress:interactive
La commande suivante exécute Simorgh et Cypress:
CYPRESS_APP_ENV=local CYPRESS_UK=true CYPRESS_SMOKE=true yarn test:e2e
CYPRESS_APP_ENV peut également être défini égal à «Tester» et «Live». Cypress_smoke peut être vrai ou faux. Il est vrai par défaut et exécute un sous-ensemble spécifique de tests.
Nous utilisons un phare pour tester les performances de notre page. Cependant, ceux-ci ont été déplacés de Simorgh vers nos propres processus de CD internes. Cela nous permet d'exécuter ces tests sur une représentation plus précise de Simorgh. Vous êtes libre d'exécuter vous-même un phare à partir de votre navigateur Chrome ou d'utiliser la CLI de phare de nœud.
Nommé Simorgh après l'oiseau mythologique persan. Le Simorgh est l'amalgame de nombreux oiseaux (et dans certains comptes d'autres animaux) en un seul.
Heureusement, une métaphore qui semblait apte à offrir tous les articles de la BBC dans une solution est peut-être encore plus appropriée à mesure que l'application évolue pour prendre en charge davantage de types de contenu. C'est également une référence claire à la nature internationale de nos équipes, mais aussi au désir de garantir les articles (et tout ce qui a suivi) fonctionne pour les utilisateurs dans toutes les langues que la BBC supporte.
C'est aussi un nom unique qui est pratique et, plus superficiellement, l'oiseau est très joli.