Journal Dynastie 0.1

Posté par (page perso) . Licence CC by-sa
Tags : aucun
24
7
fév.
2013

Salut tous le monde,

Encore un journal pour vous présenter un de mes projet perso. Cette fois-ci, il s'agit de Dynastie, un générateur de blog statique. Il en existe des centaines sur internet, le miens n'est ni meilleur, ni moins bon que les autres, il utilise juste des concepts qu'on ne retrouve pas ailleurs. Au delà du logiciel, c'est avant tout ces concepts que je tiens à présenter.

À la base j'avais Joomla pour CMS. C'est un peu lourd pour un petit blog qui tourne sur mon sheevaplug. Du coup, j'ai décidé de passer à un blog statique avec nginx en frontend pour améliorer le temps de réponse. Néanmoins, je ne voulais pas perdre l'édition en ligne, les commentaires, la recherche… J'ai donc crée une application Django qui gère une partie dynamique (édition, commentaires, recherches) et la génération statique.

Comme tous les autres générateurs, la partie statique s'appuie sur des templates. Sauf que ceux-ci sont au format xhtml avec des directives dyn:XXX, Dynastie est donc un pseudo moteur XSLT si on peut dire. Les articles sont enregistrés dans des fichiers séparés directement en HTML. Les méta données (titre, commentaires, catégorie…) sont stockés dans une base SQLite3. On mélange bien fort et ça génère le site et les flux RSS/Atom correspondants. L'avantage d'avoir les méta données dans une base est de pouvoir les manipuler facilement.

Concernant la génération, la règle est simple :

  • L'architecture de base est définie dans le dossier "sites/"
  • Le résultat est stocké dans le dossier "sites/_output"
  • Tous les fichiers qui ne commencent pas par "_" (les templates en général) sont copiés

Pour améliorer la réactivité du site, les fichiers HTML résultats ainsi que les JS et les CSS sont pré compressés en gzip. nginx utilise directement les fichiers pré compressés.

Quand un lecteur entre un commentaire, celui-ci est transmis au serveur et la page est re générée à la volée. Idem pour la recherche : on envoie une requête au serveur et la liste des résultat est générée (mais non persistante). Contre le SPAM des robots, j'utilise une astuce : il y a deux champs pour l'email. Le premier nommé "email" et invisible par CSS, et le second nommé "mel". Si le premier champs (email) est rempli, on n'enregistre pas le commentaire car il y a de fortes chances qu'il provienne d'un robot (comme quoi, l'appellation mel est utile ;) ).

Process de Dynastie

Voilà pour le gros des idées, la suite est plus classique :

  • Index dans l'ordre anti chronologique
  • Categories
  • Tags
  • Flux RSS/Atom
  • Commentaires (dynamiques et sans Disqus)
  • Recherche (dynamique)
  • éditeur WYSIWYG en ligne
  • Coloration syntaxique (avec Pygments)
  • Prévisualisation
  • Multi blogs
  • Multi utilisateurs
  • On ne regénère que ce qui est nécessaire

Le template de mon blog est contenu dans les sources du projet. Ça permet d'avoir un exemple de tous ce qui a été implémenté (et c'est pratique pour mon dev perso :)). En réalité, ça couvre surtout mon besoin personnel et n'a pas forcément vocation à être aussi générique qu'un Pelican (même si ça reprend les fonctionalités principales).

Page du projet

  • # Et la démo ?

    Posté par (page perso) . Évalué à 4.

    Ce serait bien d'avoir l'URL d'un blog généré avec ce soft pour voir à quoi ça ressemble dans la vraie vie !

  • # Commentaires

    Posté par (page perso) . Évalué à 2.

    Comment tu as géré la partie commentaire en dynamique ?
    Je suis intrigué mais surtout intéressé.

    La réalité, c'est ce qui continue d'exister quand on cesse d'y croire - Philip K. Dick

    • [^] # Re: Commentaires

      Posté par (page perso) . Évalué à 2.

      Toute la magie vient du fait que j'ai deux "serveurs" :

      1. blog.soutade.fr servit par nginx (/xxx/dynastie/sites/blog.soutade.fr_output/) et qui sert aussi de proxy
      2. dynastie.soutade.fr servit par Apache (/xxx/dynastie/)

      Dans le site statique, il y a un formulaire de commentaire qui pointe vers "/comment/add/dyn:post_id/dyn:comment_id". Le premier id étant celui du post, et le second celui du commentaire parent (dans ce cas c'est pratique d'avoir une bdd pour faire du SQL !).

      Dans la config du proxy, je redirige "/comment" vers dynastie.soutade.fr

      Une fois la page re générée, je me sers du HTTP_REFERER pour faire la redirection inverse (vers le site d'origine), sans oublier de désactiver le cache (sinon nginx sert la page d'origine).

      • [^] # Re: Commentaires

        Posté par (page perso) . Évalué à 3. Dernière modification le 08/02/13 à 08:13.

        Fort joli, mais lourd quand même : 2 serveurs pour un blog léger… as-tu comparé le besoin CPU par rapport à du php caché avec eaccelerator?

        Autre question : quel est le pourcentage de commentaires rejetés avec ton champ email caché?

        ⚓ À g'Auch TOUTE! http://afdgauch.online.fr

        • [^] # Re: Commentaires

          Posté par (page perso) . Évalué à 1.

          Au contraire, c'est très léger, puisque le second serveur (lourd) n'intervient QUE lorsqu'il y a un nouveau commentaire (ou recherche), donc rarement. Tandis que nginx envoie directement les pages compressées au client.

          Je n'enregistre pas le taux de rejet, mais depuis que j'ai mis cette technique en place, je n'ai plus aucun SPAM (j'en avais un à deux par jours avant).

      • [^] # Re: Commentaires

        Posté par (page perso) . Évalué à 3.

        Ah ! Je vois la un cas d'utilisation parfait pour mongrel2 du grand trolleur en chef Zed Shaw.

        Mongrel2 est en fait un frontend qui redirige les requêtes selon une config fort simple (et fort bien documentee). L’intérêt de Mongrel2 est qu'il intègre justement dans lui-même les besoins les plus communs :

        • fichiers statiques
        • proxy
        • traitement dynamique de requêtes

        Le plus sexy est que cette dernière partie repose sur du Publish-Subscribe via 0mq : ce n'est pas mongrel2 qui bosse, mais des processus a part. Tu peux donc avoir un nombre quelconque de worker derrière : tu es prêt pour le cloud ! Plus sérieusement, je trouve cette solution bien pratique si tu veux migrer facilement vers une autre machine, ou si tu veux pouvoir soutenir ton blog linuxfrisé et croulant sous le nombre de commentaires. Ou tout simplement si tu veux te la jouer Big Data.

        Ça serait sympa a essayer, tiens…

    • [^] # Re: Commentaires

      Posté par . Évalué à 9.

      les commentaires sont stockés sur Facebook ou twitter. Les avantages sont multiples.
      - Pas besoin de modération,
      - Ca crée de l'activité sur les réseaux qui amène du monde sur le blog
      - Pas de base de données.

      /o\

  • # Nginx est donc une dépendance ?

    Posté par . Évalué à 2. Dernière modification le 08/02/13 à 09:28.

    Salut,

    Ca à l'air cool ton petit moteur :)

    Par contre une chose m'interpelle

    les JS et les CSS sont pré compressés en gzip. nginx utilise directement les fichiers pré compressés.

    Est-ce que ça veut dire que ton serveur oueb doit supporter le pré-compressage ? Si oui, Apache est-il capable de le faire (je devrait RTFM, mais c'est vendredi, la flemme.) ? Dans le cas opposé y'a t'il une configuration du moteur qui permette de s'en passer ?

    • [^] # Re: Nginx est donc une dépendance ?

      Posté par (page perso) . Évalué à 2.

      En fait il génère les .html, puis les compresses. On a donc les deux formats dans le répertoire de sortie. Du coup, nginx n'est pas indispensable (même si c'est le meilleur pour servir des fichiers statiques).

      Il me semble qu'il y a un module Apache pour les fichiers pré compressés, mais ce n'est pas dans l'installation par défaut.

      Certains iront même jusqu'à faire tourner le tout dans le serveur intégré de Django !

  • # j'aimes beaucoup ta solution

    Posté par . Évalué à 1.

    hello,

    As tu intégré une passe d'optimisation purement HTML lors de la phase de compilation ?
    minification, regroupement, chargement progressif d'image, des trucs que ferait google mod_pagespeed en somme.

    Quid de la qualité de développement, des impressions, avec ce couple xslt + html ?

    Sinon en l'état, il y a un point qui me chiffonne tout de même.
    L'opération de post de commentaire, le click, est elle complètement chaînée de proche en proche à l'opération de régénération, ou bien le fais tu à intervalle régulier ?

    a+

    • [^] # Re: j'aimes beaucoup ta solution

      Posté par (page perso) . Évalué à 1.

      Salut,

      Dans l'ordre :

      minification

      Les fichiers (HTML, JS, CSS) sont compressés en gzip, donc ce n'est pas utile.

      regroupement

      Tout (JS, CSS) dans un fichier ? Si c'est le cas, je préfère avoir des fichiers indépendants qui ne seront téléchargés qu'une seule fois. Néanmoins, je n'utilise qu'un seul JS et qu'une seule CSS.

      chargement progressif d'image

      Non. Je laisse à nginx le soin d'optimiser ce service.

      Quid de la qualité de développement, des impressions, avec ce couple xslt + html ?

      Mon blog n'étant pas très complexe, je n'ai pas forcément tous les éléments en main pour comparer. Mais, le gros avantage est que pour la syntaxe, c'est du xml, donc "lisible". Ce que je veux dire, c'est que ce n'est pas une syntaxe exotique.

      Le principal point faible est, peut être, un manque de définition forte (règle stricte) des actions des balises : quand j'ajoute quelque chose, c'est que j'en ai besoin.

      Par contre un point intéressant, est que j'utilise un système d'inclusion de template (à 1 niveau). Ça permet de faire des modifications rapides et globales (exemple : j'ajoute un élément à mon menu). Je te conseille de regarder le fichier template de base ainsi que le template d'index (qui inclut le template de base).

      Sinon en l'état, il y a un point qui me chiffonne tout de même.
      L'opération de post de commentaire, le click, est elle complètement chaînée de proche en proche à l'opération de régénération, ou bien le fais tu à intervalle régulier ?

      C'est une opération à la demande.

      • [^] # Re: j'aimes beaucoup ta solution

        Posté par (page perso) . Évalué à 1.

        J'ai aussi une balise spéciale pour remplacer une (ou plusieurs) valeur(s) à l'intérieur d'une chaine de caractères :
        <dyn:replace div_name="img" some_attribute="dyn:blog_id">
        Qui donne
        <img some_attribute="4">

        PS : Je n'avais pas fait attention au titre du commentaire, merci :)

      • [^] # Re: j'aimes beaucoup ta solution

        Posté par . Évalué à 1.

        ah faut que je regarde ce truc de gzip. C'est le genre de mod que je fais installé par défaut, mais j'avoue ne pas connaitre sont efficacité sur des fichiers minifiés par apport aux coûts cpu de compression.

        Au sujet de xml, oui c'est lisible, mais c'est aussi verbeux. Alors autant pour templater de bloc à bloc ça me parait censer, autant pour faire du string replace c'est moi qui bloque.
        Mais ce n'est ptet pas le genre de problèmes que tu as eu à résoudre.
        Je vais aller voir cela dans les sources à l'occasion.

        Pour ce qui est de la génération des commentaires, ok c'est clair.
        Je me posais cette question car je me demandais combien de temps était pris pour générer les commentaires et les impacts sur l’hébergement d'une solution de ce type là.

        • [^] # Re: j'aimes beaucoup ta solution

          Posté par (page perso) . Évalué à 1.

          ah faut que je regarde ce truc de gzip. C'est le genre de mod que je fais installé par défaut, mais j'avoue ne pas connaitre sont efficacité sur des fichiers minifiés par apport aux coûts cpu de compression.

          Le coût CPU est nul puisque la compression est faite lors de la génération et non lors de la requête. Aujourd'hui la majorité des réponses HTTP sont compressées par le serveur.

          Au sujet de xml, oui c'est lisible, mais c'est aussi verbeux. Alors autant pour templater de bloc à bloc ça me parait censer, autant pour faire du string replace c'est moi qui bloque.
          Mais ce n'est ptet pas le genre de problèmes que tu as eu à résoudre.

          Effectivement, le XML est plutôt naturel à utiliser sauf pour la substitution intra chaîne. J'ai donc dû utiliser une petite "astuce". C'est presque bien, mais ce n'est pas ce qu'il y a de mieux comparé aux autres solutions de templates.

          Je me posais cette question car je me demandais combien de temps était pris pour générer les commentaires et les impacts sur l’hébergement d'une solution de ce type là.

          La génération d'une page avec un nouveau commentaire est plutôt rapide : de l'ordre de quelques secondes (3-5 secondes). Sachant que je suis sur un SheevaPlug auto hébergé, donc assez limité en ressources et bande passante interne (bus, flash, …) et externe.

  • # Dans le même genre : Stog

    Posté par . Évalué à 2. Dernière modification le 10/02/13 à 22:15.

    J'utilise Stog parce qu'il est codé en OCaml, et je trouve ça sympa. C'est assez proche; on écrit des fichiers XML en donnant des règles de ré-écriture en OCaml ("si tu rencontres la balise 'machin', tu fais ceci cela avec le contenu") et le générateur les applique tant qu'il peut, en espérant obtenir un HTML potable au final. Concrètement la plus grosse partie des billets est écrite avec Markdown/Pandoc dans un <markdown command="pandoc" args="…."><![CDATA[ … ]]></markdown>, avec les règles qui vont bien.

    Les métadonnées font partie des billets (ce sont des attributs dans l'élément <post> racine), et je trouve ça assez commode. Je vois l'intérêt technique d'utiliser du SQLite là-dessus, mais ça m'a l'air peut-être un peu plus prise de tête. Du coup le moteur Stog doit reprocesser ces données à chaque génération, mais en pratique ça va vite et il y a un système de cache pour éviter les calculs (trop) inutiles.

    Enfin, pour les commentaires j'utilise Disqus. C'est centralisé et pas libre, ce que je regrette, mais je n'ai vraiment pas du tout envie de m'occuper de combattre le spam moi-même et ils ont des filtres efficaces et de bons outils de modérations. J'aimerais bien un pendant libre de Disqus comme Identi.ca l'est à Twitter, mais pour l'instant mes recherches n'ont rien donné d'utilisable.

    L'intérêt de ne pas gérer les commentaires localement, c'est que mon site est vraiment entièrement statique, ce qui est au poil pour la sécurité.

    • [^] # Re: Dans le même genre : Stog

      Posté par (page perso) . Évalué à 1.

      Stog se distingue par l'utilisation de directives XML et du langage OCaml. Pour le reste, il y a de fortes similitudes avec l'existant (ligne de commande, méta données, Markdown…). Ma solution est plutôt hybride entre application web et site statique.

      L'intérêt de ne pas gérer les commentaires localement, c'est que mon site est vraiment entièrement statique, ce qui est au poil pour la sécurité.
      Les commentaires et la recherche sont optionnels. Mais je suis d'accord avec toi, il y a potentiellement une faille.

      • [^] # Re: Dans le même genre : Stog

        Posté par . Évalué à 2. Dernière modification le 11/02/13 à 15:17.

        J'ai déjà vu ce système d'actions dynamiques qui provoquent une re-génération statique mis en place. L'exemple qui me vient à l'esprit en premier est un blog peu connu (et qui n'est plus en ligne à ma connaissance) mais dont les sources sont disponibles en ligne, The Lambda Church, où les commentaires sont gérés par… un frontend PHP qui appelle un shell script qui ajoute le commentaire à un fichier texte versionné sous darcs et rédigé dans un format de markup permettant une génération facile de HTML derrière.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.