31 votes

Quel est le moyen le moins redondant de rendre un site avec HTML généré par JavaScript à ramper ?

Après avoir lu la politique de Google sur la rendu explorable des contenus générés par Ajax, ainsi que de nombreux blog posts de développeurs et discussions sur Stackoverflow sur le sujet, je suis arrivé à la conclusion qu'il n'y a pas de moyen de rendre explorable un site généré uniquement en JavaScript/Ajax. Un site sur lequel je travaille actuellement n'indexe pas une bonne partie de son contenu. Toute la couche de présentation de notre contenu non indexé est construite en JavaScript en générant du HTML à partir de JSON retourné par des appels de services web basés sur Ajax, et nous pensons que Google n'indexe pas le contenu à cause de cela. Est-ce correct ?

La seule solution semble être d'avoir aussi une version "de secours" du site pour les moteurs de recherche (en particulier Google) où tout le HTML et le contenu seraient générés comme cela a été fait traditionnellement, du côté serveur. Pour les clients avec JavaScript activé, il semble que nous pourrions utiliser essentiellement la même approche que nous faisons maintenant : utiliser JavaScript pour générer du HTML à partir de JSON chargé de manière asynchrone.

D'après ce que j'ai pu lire, la meilleure pratique actuelle pour appliquer le principe DRY dans la création de sites Ajax générés explorables comme décrit ci-dessus est d'utiliser un moteur de templating qui peut utiliser les mêmes modèles côté client et côté serveur. Pour les clients avec JavaScript activé, le moteur de templating côté client, par exemple mustache.js, transformerait les données JSON envoyées par le serveur en HTML tel que défini par sa copie d'un fichier de modèle. Et pour les moteurs de recherche et les clients sans JavaScript, l'implémentation côté serveur du même moteur de templating, par exemple mustache.java, opérerait de manière similaire sur sa copie du même fichier de modèle exact pour produire du HTML.

Si cette solution est correcte, en quoi est-elle différente des approches utilisées il y a 4 ou 5 ans par les sites avec une forte présence frontale, où les sites devaient essentiellement maintenir deux copies du code de templating, une pour les utilisateurs avec JavaScript activé (pratiquement tout le monde) et une autre copie (par exemple dans FreeMarker ou Velocity) pour les moteurs de recherche et les navigateurs sans JavaScript activé (pratiquement personne) ? Il semble qu'il devrait y avoir une meilleure façon de faire les choses.

Cela implique-t-il que deux couches de modèles de templating doivent être maintenues, une côté client et une côté serveur ? Dans quelle mesure est-il conseillé de combiner ces modèles côté client avec un framework front-end MVC (MV/MVVC) comme Backbone.js, Ember.js, ou YUI App Library ? Comment ces solutions affectent-elles les coûts de maintenance ? Serait-il préférable d'essayer de le faire sans introduire de nouveaux frameworks - un nouveau moteur de templating et un framework front-end MVC - dans la pile technologique d'une équipe de développement ? Y a-t-il un moyen de le faire de manière moins redondante ?

Si cette solution n'est pas correcte, alors y a-t-il quelque chose que nous ne comprenons pas et que nous pourrions faire mieux avec notre JavaScript pour maintenir notre structure actuelle de génération asynchrone de HTML à partir de JSON et l'indexer, afin de ne pas avoir à introduire quelque chose de nouveau dans la pile d'architecture ? Nous aimerions vraiment éviter de devoir mettre à jour deux versions de la couche de présentation lorsque les besoins métier changent.

10voto

Simple As Could Be Points 3906

Pourquoi n'ai-je pas pensé à cela avant! Il suffit d'utiliser http://phantomjs.org. C'est un navigateur webkit sans tête. Il suffirait de créer un ensemble d'actions pour parcourir l'interface utilisateur et capturer le html à chaque état souhaité. Phantom peut convertir le html capturé en fichiers .html pour vous et les enregistrer sur votre serveur web.

Tout serait automatisé à chaque construction/commit (PhantomJS est piloté en ligne de commande). Le code JS que vous écrivez pour parcourir l'interface utilisateur ne fonctionnerait plus lorsque vous modifiez l'interface, mais cela ne devrait pas être pire que les tests d'interface utilisateur automatisés, et c'est juste du Javascript donc vous pouvez utiliser les sélecteurs jQuery pour sélectionner des boutons et les cliquer.

Si je devais résoudre le problème de référencement, c'est certainement l'approche que je prototyperais. Crawl and save, baby. Oui monsieur.

3voto

Simple As Could Be Points 3906

Je pense qu'une combinaison de quelques technologies et d'un petit hack codé manuellement que vous pourriez réutiliser vous aiderait. Voici mon idée folle et incomplète. Étape 1 :

  • Utilisez des templates côté client, comme vous le suggérez. Mettez chaque template dans un fichier séparé (pour pouvoir les réutiliser facilement entre le client et le serveur)
  • Utilisez le templating underscore.js, ou reconfigurez Mustache. De cette façon, vous obtiendrez des délimiteurs de style ERB dans votre template, identiques au <%= %> de Java.
  • Comme ce sont des fichiers séparés, vous voudrez commencer à développer des modules CommonJS avec un chargeur de modules comme curl.js ou require.js pour charger les templates dans votre code côté client. Si vous ne faites pas de développement modulaire, c'est assez génial. J'ai commencé il y a environ un mois. Cela semble difficile au début mais c'est simplement une manière différente d'encapsuler votre code : http://addyosmani.com/writing-modular-js/

Ok, donc maintenant vous avez des templates isolés. Maintenant, nous devons juste trouver comment construire une page plate à partir d'eux sur le serveur. Je ne vois que deux approches. Étape 2 :

  • Vous pourriez annoter votre JS afin que le serveur puisse le lire et voir un chemin par défaut pour les appels ajax et quels templates ils lient, ensuite le serveur peut utiliser les annotations pour appeler les méthodes du contrôleur dans le bon ordre et remplir une page plate.
  • Ou vous pourriez annoter vos templates pour indiquer quel contrôleur ils devraient appeler et fournir des exemples de paramètres d'appel. Cela serait facile à maintenir et bénéficierait aux développeurs frontend comme moi qui doivent constamment rechercher les URLs des contrôleurs. Cela dirait également à votre code backend quoi appeler.

J'espère que cela vous aidera. Curieux de connaître la meilleure réponse à cela. Un problème intéressant.

1voto

Kernel James Points 1676

Utilisez les modèles Distal. Votre site Web est en HTML statique qui est parcourable et Distal traite le HTML statique comme un modèle.

0voto

Roger Alsing Points 5542

Nous utilisons PhantomJS à cette fin tout aussi simplement que possible. Cela fonctionne très bien si vous avez le droit de l'utiliser sur votre hôte.

Si ce n'est pas une option ou si vous ne voulez tout simplement pas vous en occuper vous-mêmes. Nous avons un service gratuit pour le faire. Voir cet article pour plus d'informations : http://rogeralsing.com/2013/08/06/seo-indexing-angularjs-sites-or-other-ajax-sites-with-wombit-crawlr/

0voto

tomaszs Points 5633

J'ai trouvé une solution qui ne nécessite pas Java, Node.js ou tout autre moyen de copier de manière redondante un site Web générant du code JS. De plus, elle prend en charge tous les navigateurs.

Donc, ce que vous devez faire, c'est fournir la capture d'écran pour Google. C'est la meilleure solution, car vous n'avez pas besoin de vous embêter avec d'autres URL et ainsi de suite. De plus, vous n'ajoutez pas de noscript à votre site de base, donc il est plus léger.

Comment faire une capture d'écran ? Phantomjs, HTMLUnit, etc. nécessitent un serveur où vous pouvez le mettre et l'appeler. Vous devez le configurer et le combiner avec votre site Web. Et c'est le bazar. Malheureusement, il n'y a pas de navigateur PHP sans tête. C'est évident en raison des spécificités de PHP.

Alors quelle est l'autre façon d'obtenir une capture d'écran ? Eh bien... si l'utilisateur ouvre le site Web, vous pouvez obtenir la capture de ce qu'il voit avec JS (innerHTML).

Donc, ce que vous devez faire, c'est :

  • vérifier si vous avez besoin d'une capture d'écran pour votre site (si vous l'avez, vous n'avez pas besoin d'en prendre une autre)
  • envoyer cette capture d'écran au serveur pour l'enregistrer dans un fichier (PHP gère la demande POST avec la capture d'écran et l'enregistre dans un fichier)

Et si le robot Google visite votre site avec un hash bang, vous obtenez le fichier de la capture d'écran pour la page demandée.

Choses à résoudre :

  • sécurité : vous ne voulez pas de script de l'utilisateur ou de son navigateur (injection) enregistré dans la capture d'écran, peut-être est-il préférable que vous puissiez générer des captures d'écran (voir le plan du site ci-dessous)
  • compatibilité : vous ne voulez pas enregistrer à partir de n'importe quel navigateur mais de celui qui supporte le mieux votre site Web
  • ne pas déranger les mobiles : ne pas utiliser les utilisateurs mobiles pour générer des captures d'écran afin que la page ne soit pas plus lente pour eux
  • alternance : si vous n'avez pas de capture d'écran de sortie de site Web standard - ce n'est pas bon pour Google, mais c'est quand même mieux que rien

Il y a aussi une chose : toutes les pages ne seront pas visitées par les utilisateurs mais vous avez besoin de captures d'écran pour Google avant qu'ils visitent.

Alors que faire ? Il y a aussi une solution pour cela :

  • générer un plan du site qui contient toutes les pages de votre site Web (il doit être généré en temps réel pour être à jour, et le logiciel de crawler n'aide pas car il n'exécute pas de JS)
  • visiter de toute façon les pages du plan du site qui n'ont pas de capture d'écran. Cela appellera le code de capture d'écran et le générera correctement
  • visiter régulièrement (quotidiennement ?)

Mais hey, comment visiter toutes ces pages ? Eh bien. Il y a quelques solutions pour cela :

  • écrire une application en Java, C# ou tout autre langage pour obtenir les pages à visiter du serveur et les visiter avec un contrôle de navigateur intégré. Ajoutez ceci à votre planning sur le serveur.
  • écrire un script JS qui ouvre les pages requises dans un iFRAME l'une après l'autre. Ajoutez ceci à votre planning sur un ordinateur.
  • ouvrez simplement le script mentionné ci-dessus manuellement si votre site est principalement statique

N'oubliez pas non plus de rafraîchir les anciennes captures d'écran de temps en temps pour les remettre à jour.

J'espère avoir de vos nouvelles sur ce que vous pensez de cette solution.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X