[đ ] RĂ©duire le temps de build du blog multilingue de 21 minutes Ă environ 1 minute
âš RĂ©sumĂ© de GPT-5.5 ă
RĂ©cit du suivi, avec le profil Jekyll, dâun build qui dĂ©passait 20 minutes aprĂšs lâextension multilingue, puis de la suppression des rendus rĂ©pĂ©tĂ©s et des scans de tout le site jusquâĂ descendre Ă 1 minute 50 secondes.
Dans lâarticle prĂ©cĂ©dent sur lâintroduction multilingue, jâai ajoutĂ© au blog une structure dâexploitation multilingue.
Au dĂ©but, jâen Ă©tais assez fier.
ko, en, ja, zh-Hans, es, pt-BR, fr, id.
Il y avait des articles, des menus, du hreflang, et les vues Ă©taient partagĂ©es. Vu de lâextĂ©rieur, câĂ©tait devenu un blog multilingue assez plausible.
Mais un autre problĂšme est apparu tout de suite.
Le build prenait beaucoup trop de temps.
Le premier production build ressemblait Ă ceci.
done in 1311.791 seconds
21 minutes et 52 secondes.
Ce nâest pas un chiffre quâun simple blog devrait produire. Si corriger un seul article fait dĂ©passer 20 minutes de build, je finirai par passer plus de temps Ă attendre les builds quâĂ Ă©crire.
Au dĂ©but, on pouvait ĂȘtre tentĂ© de penser simplement : âComme il y a maintenant huit langues, forcĂ©ment câest devenu plus lent.â
Mais câĂ©tait une conclusion beaucoup trop rapide.
Le nombre de pages avait bien augmentĂ©. Mais atteindre les 20 minutes signifiait quâil y avait autre chose. Alors cette fois, au lieu de corriger au feeling, jâai lancĂ© jekyll build --profile.
Premier coupable : le JSON du calendrier était injecté dans toutes les pages
Jâai dâabord regardĂ© la taille de _site.
_site: 1.2G
HTML total: environ 840MB
840 Mo de HTML pour un blog statique.
Ăa nâavait aucun sens.
Jâai ouvert un article reprĂ©sentatif, et la raison est apparue immĂ©diatement. Le calendrier de la sidebar injectait, en inline, la liste JSON complĂšte des articles de la langue concernĂ©e dans chaque page dâarticle.
<script type="application/json" data-calendar-posts>
[
...
]
</script>
Et ce nâĂ©tait pas tout.
Pour fabriquer la liste de fallback du calendrier, Liquid parcourait de nouveau toute la liste des articles pour chaque date. MĂȘme les articles qui ne correspondaient pas Ă la condition produisaient une Ă©norme quantitĂ© dâespaces Liquid. Lâinterface visible Ă©tait petite, mais Ă lâintĂ©rieur du HTML se cachaient de gigantesques blocs dâespaces et de listes rĂ©pĂ©tĂ©es.
Ce nâĂ©tait pas un problĂšme de fonctionnalitĂ©. CâĂ©tait un problĂšme de structure.
Le calendrier nâavait pas besoin que le serveur fabrique un HTML complet sur chaque page. Le JS savait dĂ©jĂ dessiner le calendrier dynamiquement. Dans ce cas, le serveur devait seulement fournir le squelette du mois courant et le chemin vers le fichier de donnĂ©es.
Jâai donc sorti les donnĂ©es du calendrier dans des fichiers JSON sĂ©parĂ©s par langue.
/assets/data/calendar-posts-ko.json
/assets/data/calendar-posts-en.json
/assets/data/calendar-posts-ja.json
/assets/data/calendar-posts-zh-Hans.json
/assets/data/calendar-posts-es.json
/assets/data/calendar-posts-pt-BR.json
/assets/data/calendar-posts-fr.json
/assets/data/calendar-posts-id.json
Et il ne reste plus que ceci dans la page.
data-calendar-posts-src="/assets/data/calendar-posts-en.json"
Le résultat a baissé immédiatement.
1311.791 secondes -> 745.273 secondes
Presque la moitiĂ© avait disparu, mais câĂ©tait encore long.
Câest lĂ que jâai compris.
Le calendrier Ă©tait un gros coupable, mais ce nâĂ©tait pas le seul.
DeuxiÚme coupable : les statistiques du menu étaient calculées 80 000 fois
Le profil suivant était encore plus flagrant.
_includes/sidebar-nav-stats.html 81120 calls 173.084s
_includes/masthead.html 2704 calls 319.860s
_includes/seo.html 2704 calls 119.985s
sitemap.xml 1 call 117.495s
Le plus drĂŽle, câĂ©tait sidebar-nav-stats.html.
Cet include est un petit fragment qui ajoute le nombre dâarticles et lâheure du dernier article Ă cĂŽtĂ© de chaque catĂ©gorie de la sidebar.
Par exemple, quelque chose comme ceci.
Daily Review (310) 1 days ago
Devlog (24) 2 days ago
Mais chaque fois que ce petit fragment était appelé, il triait toute la liste des articles, puis la filtrait de nouveau.
Pour chaque élément de menu de chaque langue.
Sur chaque page.
Et encore une fois dans la sidebar desktop et dans le menu mobile.
Résultat : 81 120 appels.
Cette valeur nâa pas besoin dâĂȘtre recalculĂ©e pour chaque page. Si la langue et lâURL du menu sont les mĂȘmes, le rĂ©sultat est le mĂȘme. Je lâai donc remplacĂ©e par include_cached de jekyll-include-cache.
{% include_cached sidebar-nav-stats.html url=child.url lang=current_lang %}
Le nombre dâappels est alors devenu ceci.
81120 calls -> 210 calls
173 secondes -> 0.4 seconde
Ă ce niveau-lĂ , ce nâĂ©tait presque plus de lâoptimisation. CâĂ©tait plutĂŽt un bug attrapĂ© en plein vol.
TroisiĂšme coupable : le site scannait tout pour fabriquer les liens de langue
En ajoutant le changement de langue, jâavais mis dans masthead, seo et sitemap une logique du genre :
Cette URL existe-t-elle vraiment dans cette langue ?
Lâintention Ă©tait juste.
Il ne faut pas mettre une URL de traduction inexistante dans hreflang ou dans le menu de changement de langue. Au dĂ©but, je vĂ©rifiais donc lâexistence des URL en parcourant toutes les pages et tous les documents de collection.
Le problĂšme, câest que cela se rĂ©pĂ©tait sur chaque page.
2704 pages * site.pages scan * translated collections scan
Plus un site multilingue grandit, plus cette structure empire.
Jâai donc changĂ© de mĂ©thode.
Ce blog possÚde déjà une rÚgle pour les URL traduites.
/some/post/
/en/some/post/
/ja/some/post/
...
Et les exceptions peuvent ĂȘtre gĂ©rĂ©es sĂ©parĂ©ment comme des donnĂ©es.
Cette fois, jâai placĂ© dans _data/i18n_pending.yml lâarticle de retour de session dont la traduction Ă©tait encore en attente.
entries:
- source_url: /devlog/github-pages-blog/github-pages-blog-english-version-lessons/
locales:
- en
- ja
- zh-Hans
- es
- pt-BR
- fr
- id
Ainsi, les articles ordinaires sont reliĂ©s par la rĂšgle de prĂ©fixe, et les articles en attente retombent vers la page dâaccueil de lâautre langue. On ne scanne plus tout le site.
Lâeffet a Ă©tĂ© important.
masthead: 319.860 secondes -> 9.882 secondes
seo: 119.985 secondes -> 7.181 secondes
sitemap: 117.495 secondes -> 4.633 secondes
Et le build final sâest terminĂ© ainsi.
done in 110.344 seconds
De 21 minutes 52 secondes Ă 1 minute 50 secondes.
Ce nâest pas encore assez pour dire que le blog est rapide, mais au moins il nâest plus dans lâĂ©tat oĂč le build fait trop peur pour Ă©crire.
Ce Ă quoi jâai fait attention en corrigeant
Si lâon ne regarde que la vitesse, cette optimisation a lâair facile.
Mais ce qui demandait vraiment de lâattention, câĂ©tait de ne pas casser les fonctionnalitĂ©s.
Sur un site multilingue en particulier, on peut facilement se rĂ©jouir dâun build plus rapide et crĂ©er ce genre de problĂšmes.
les liens de changement de langue mĂšnent Ă des 404
hreflang pointe vers des URL inexistantes
les traductions en attente sont exposées comme alternate aux moteurs de recherche
sur mobile, les boutons About/langue disparaissent de nouveau
le calendrier reste vide
Ă la fin, jâai donc combinĂ© vĂ©rifications navigateur et vĂ©rifications automatiques.
Voici ce que jâai vĂ©rifiĂ©.
production build réussi
les liens de changement de langue fonctionnent dans les 8 langues pour l'article de voyage en anglais
hreflang correct pour 8 langues + x-default
les articles dont la traduction est en attente retombent vers l'accueil de l'autre langue
sur mobile, About, đșđžEnglish et le calendrier s'affichent correctement
des URL multilingues représentatives répondent en 200
vérification exhaustive de la structure rendue de 2481 articles sources
parsing du JSON du calendrier vérifié
i18n post coverage errors: 0
Je nâai pas lu les 2481 articles un par un Ă lâĆil humain.
Mais au minimum, la vérification automatique a contrÎlé que les fichiers de sortie existent, que la structure des articles est rendue, que les liens de langue ne sont pas cassés et que les données du calendrier existent.
CâĂ©tait le cĆur de ce travail.
Optimiser un build, ce nâest pas seulement rĂ©duire le temps. Câest expliciter Ă nouveau les contrats des fonctionnalitĂ©s existantes.
Ce que jâai appris cette fois
Jekyll a lâair simple parce que câest un gĂ©nĂ©rateur de site statique.
Mais si Liquid commence Ă parcourir tout le site encore et encore, mĂȘme un site statique peut devenir franchement lourd.
Dans une structure multilingue surtout, les petites inefficacités deviennent immédiatement des multiplicateurs.
nombre de pages * nombre de langues * nombre de menus * nombre total d'articles
Quand ce genre de multiplication se cache quelque part, le build finit par exploser soudainement.
Ce que jâai appris cette fois est simple.
PremiĂšrement, ne pas rĂ©pĂ©ter les mĂȘmes donnĂ©es inline sur chaque page.
DeuxiĂšmement, si les mĂȘmes entrĂ©es donnent le mĂȘme rĂ©sultat, mettre lâinclude en cache.
TroisiÚmement, ne pas scanner tout le site depuis chaque page simplement pour vérifier si une URL existe.
QuatriÚmement, ne pas traiter les exceptions au feeling : les garder dans des données.
CinquiĂšmement, aprĂšs lâoptimisation, vĂ©rifier les contrats fonctionnels par des tests automatiques.
Ce blog devient peu Ă peu moins un simple blog personnel quâun systĂšme.
Câest bien, et câest fatigant.
Mais au moins, cette fois, la fatigue avait du sens.
Faire passer un build de plus de 21 minutes Ă la tranche dâune minute a Ă©tĂ©, trĂšs concrĂštement, un grand tournant.
Le blog multilingue a maintenant au moins assez dâair pour continuer Ă grandir.
Laisser un commentaire