kristenjestin.fr - v3

Site Web -

Présentation

Ce site web existe depuis que j’ai commencé à faire du développement web (2017). Une première version a été faite en PHP classique sans aucun framework. Une deuxième version où seulement le design à changé a été fait quelques mois plus tard. Un article expliquant les différentes fonctionnalités est disponible ici.

Après avoir appris et fais quelques api et site en symfony, je me suis décidé à me lancer dans la refonte complète de mon site à l’aide de ce framework.

J’ai décidé de choisir la dernière version (5.1) après avoir testé la compatibilité avec les bundles.

La conception de ce site s’est déroulée en 3 grosses étapes : le design, le site et l’administration.

Design

J’ai débuté le design en commençant par faire un figma. Ça m’a pris environ 2-3 semaines.

kristenjestin-figma-site

A la suite de ça, j’ai décidé de le refaire en HTML et CSS classique pour me rendre compte du rendu final. J’ai décidé d’utiliser gulp avec du pug et du sass.

Cela me permettait d’avoir déjà mon rendu côté front avec le code HTML découpé et le sass déjà formé pour être réutilisé telle quelle. Ça m’a pris environ 10 jours.

Développement

Pour cette partie, je me suis concentré sur le back-end.

Tâches

J’ai décidé de regrouper toutes mes tâches sur un trello. J’ai découpé ça en 7 “listes”:

  • Idea
  • Conception
  • To Do
  • Doing
  • Test
  • Done

kristenjestin-trello

Git

J’ai décidé d’héberger mon code sur github.

J’ai aussi décidé d’utiliser les github actions pour les tests automatiques.

Je lance des tests unitaires et un phpstan à chaque commit.

name: Tests
on: [push]

jobs:
    lint:
        name: Lint
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v2

            - name: Install dependencies
              run: composer install --prefer-dist --no-progress --no-suggest

            - name: PHPStan
              uses: chindit/actions-phpstan@master
              with:
                  arguments: "analyse"

    test:
        name: Test
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@master

            - name: Install dependencies
              run: composer install --prefer-dist --no-progress --no-suggest

            - name: Create Fake Files
              run: |
                  mkdir public/build
                  echo "{}" >> public/build/manifest.json
            - name: Update Databases
              run: php bin/console d:s:u --env=test --force

            - name: PHPUnit
              uses: chindit/actions-phpunit-symfony@master

Je versionne mon code à l’aide du workflow Gitflow.

Base de données

La première étape a été de faire le MCD. Le SQL étant un de mes points faibles, j’ai du m’y reprendre à 3 fois avant d’avoir un résultat qui me convienne.

kristenjestin-mcd-database

J’ai fait le choix de découper les tables Thumbnail, Content et Hero afin de pouvoir optimiser les requêtes en fonction des pages. En y réfléchissant après coup, je ne pense pas que c’était une bonne idée.

Exemple :

  • La page /articles n’a besoin que de Thumbnail
  • La page /articles/nom-article a besoin que de Hero, Content, Tag et Attachment

Symfony utilise l’ORM doctrine. Cette ORM renvoie l’objet au complet à chaque requête. Dans l’exemple de la page d’un article, si je veux renvoyer tous les Tags et mon Content dans la même requête, le résultat donnerait quelque chose comme ça :

TitleSummarySlugContentTag
AudioksCeci est un sommaire …audioksCeci est un contenu de 800 caractèresC#
AudioksCeci est un sommaire …audioksCeci est un contenu de 800 caractèresWPF
AudioksCeci est un sommaire …audioksCeci est un contenu de 800 caractèresIllustrator

Dans ce cas, si le content est dans la table article, tout le contenu est renvoyé plusieurs fois. Dans mes tests, avec un très grand contenu et 5-6 tags, la requête avec une table Content en plus, mettais moins de temps à s’exécuter.

Il est préférable de faire une seule grosse requête plutôt que plusieurs petites. Mais au vu de mes tests, découpés en 2 tables, me procurait de meilleures performances (50-150ms). Étant donné que la plupart de mes contenus ne sont pas grand et que la plupart des articles n’ont pas beaucoup de tags, je ne sais pas si c’était le meilleur choix.

Article

Le contenu d’un article est géré avec du markdown. J’ai créé des tags spéciaux qui me permette de lier des images (Attachment) en base de données à mon contenu.

Seo

Pour cette “3eme” version du site, j’ai essayé de me concentrer un peu plus sur le SEO.

Pendant la conception, j’ai fait attention à utiliser des tags HTML5.

J’ai ajouté les tags meta pour les images, la description, etc. J’ai aussi ajouté ceux de Twitter et Facebook.

Pour l’affichage de mes articles, j’ai fait le choix de placer l’id puis le slug de l’article /articles/ID-SLUG.

Cette méthode permet de garder un lien lisible, sachant que le slug est à la fin. Elle permet aussi, en cas de changement de slug, de conserver un lien vers l’article (si le slug n’est pas correct, une redirection 302 est faite vers le lien avec le vrai slug).

Sitemap

Le sitemap est généré a la volé via des urls précises et via les données en base pour les articles et les tags.

<sitemapindex>
    <sitemap>
        <loc>https://kristenjestin.fr/sitemap_static.xml</loc>
    </sitemap>
    <sitemap>
        <loc>https://kristenjestin.fr/sitemap_articles.xml</loc>
    </sitemap>
    <sitemap>
        <loc>https://kristenjestin.fr/sitemap_articles_categories.xml</loc>
    </sitemap>
    <sitemap>
        <loc>https://kristenjestin.fr/sitemap_articles_tags.xml</loc>
    </sitemap>
</sitemapindex>

Cache

Le cache a été un long moment de réflexion. Ce site étant pratiquement statique (le contenu des pages et des articles ne change pratiquement jamais). J’ai opté pour mettre en cache toutes les pages du site. A chaque première visite, la page est mise en cache jusqu’à ce qu’elle soit manuellement détruite. Cette façon de fonctionner me permet d’avoir de meilleur performance étant donné qu’il n’y a plus de requête n’y de traitement.

Cette méthode a quand même quelque soucis, le footer étant composé de l’année en cours, mon âge affiché sur l’accueil, ou les “posté il a 2 mois” des articles. Tous les textes qui sont liés à une date posent des soucis avec cette méthode.

Pour contrer ces quelques soucis, je vais devoir supprimer le cache tous les ans et le jour de mon anniversaire. Pour le “posté il y a”, j’affiche la date de publication via du JavaScript, je le remplace par le texte “il y a”.

Ce système de cache repose sur des tags. Chaque page mise en cache est. liée à un tag. Je peux ensuite demander la suppression du cache en fonction d’un tag.

Exemple :

Ma page d’accueil et ma page des articles ont toutes les 2 le tag “articles”. Au moment où je créer, modifie ou supprime un article, je demande la suppression du cache avec le tag articles. J’ai donc un remplacement du cache lors d’un changement sur un article.

L’administration me permet aussi de crawler tout le site afin de régénérer tout le cache. Je peux aussi le faire page par page.

Peaufinage

Après avoir terminé toutes mes tâches, je me suis concentré sur le “peaufinage” du site.

J’ai ajouté la gestion de turbolink pour avoir de meilleures performances au changement de page.

J’ai aussi ajouté du Scroll reveal sur quelques éléments du site.

J’ai créé une route qui génère le sitemap et qui le met en cache.

J’ai ajouté un système de log. En cas d’exception, le système m’envoi un mail.

Administration

Pour la partie administration, j’ai utilisé un template gratuit.

Cette administration est un CRUD de toutes mes tables.

Il a aussi une partie “stat” qui affiche nombre de visites du jour et du mois.

Hébergement

J’ai décidé d’héberger cette nouvelle version du site chez OVH (jusqu’a présent, j’étais chez Livehost). Après quelques mois d’utilisation de l’abonnement “Perso”, je me rends compte que par moment le site met extrêmement longtemps à chargé. C’est sans doute dû au fait que c’est un hébergement mutualisé. Je pense changer d’hébergeur à la fin de mon abonnement chez eux.

Prochaine version

  • Ajouter une gestion des alertes avec tâches cron
  • Ajouter une gestion des urls dans l’édition des articles

Conclusion

C’est un des premiers vrais projets que j’arrive à terminer et à mettre en production. C’est la première fois que j’allais aussi loin dans les phases de “DevOps”. J’ai réussi à bien découper les parties : base de données, puis le back-end, le front-end et pour finir le back-office. Le repo de grafikart m’a aidé dans beaucoup de process notamment la gestion de la page de contact (anonymisation des données, empêcher le spam, etc) et la gestion des images.