Petit guide du templating client

Sylvain Pollet-Villard

Avez-vous déjà manipulé de grands pans de HTML en JavaScript, et trouvé ça peu lisible et fastidieux ? Les templates sont là pour vous simplifier la vie et produire du code plus lisible et maintenable. Cet article fait le tour des principales solutions de templating existantes en JavaScript pour vous permettre de trouver la bibliothèque qu'il vous faut.
Commentez

- Titre : Petit guide du templating client

- Auteur : Sylvain Pollet-Villard

- Parution : 13 octobre 2013

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2013 Sylvain Pollet-Villard. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Qu'est-ce que le templating ?

- III. Pourquoi délocaliser le templating côté client ?

- IV. Le faux argument de la performance

- V. Tour d'horizon des bibliothèques de templating

- V-A. La vieille méthode : innerHTML ou jQuery.append

- V-B. DOMjs

- V-C. John Resig micro templating

- V-D. mustache

- V-E. PURE

- VI. Quel templating choisir ?

- VII. Aller plus loin

- VII-A. Le data-binding

- VII-B. Gérer l'internationalisation côté client

- VIII. Conclusion

- IX. Remerciements et références

I - Introduction

Les navigateurs ne cessent de s'améliorer et les applications Web mettent de plus en plus à profit le gain de performance des moteurs d'exécution JavaScript ainsi que les nouvelles API offertes par les évolutions des langages côté client. Le requêtage dynamique permis par AJAX fut à lui seul une petite révolution pour les sites Internet, ouvrant la porte à des sites plus interactifs, plus communicants. Permettant de récupérer des données serveur à la demande sans changer de page et sans recharger les éléments communs du site tels que sa structure HTML, ses bibliothèques JavaScript et ses feuilles de style CSS , AJAX fut une composante technologique essentielle pour permettre l'essor du Web moderne représenté par les réseaux sociaux, les webmails et autres « Rich Internet Applications ».

Il se trouve également être à un virage dans l'histoire de l'innovation des technologies Web. En effet, les années 1995 à 2005 ont été marquées par la « bulle Internet » et le « Web 2.0 ». Mais la plupart des innovations de cette décennie résidaient dans les technologies de gestion, de stockage et de génération de contenu employées côté serveur. La première version publique de PHP est apparue en 1995, tandis que JavaEE et ASP.NET sont apparues au début du millénaire pour répondre aux nouveaux usages et besoins des sites de publication et d'échange. L'outillage côté serveur s'étant considérablement amélioré, il s'agissait dès lors de se pencher du côté client.

Emporté par la vague d'AJAX, c'est tout le développement Web front-end qui bénéficia d'un essor depuis. La préparation de la norme HTML5, la révolution mobile et les applications Web multicanaux ont également concouru à cet engouement autour du navigateur. Le rythme de développement de tous les navigateurs s'est accéléré tout comme l'apparition de nouvelles API, bibliothèques et autres outils de développement côté client. De nouveaux modèles de conception suivant cette tendance voient le jour, tels que les Single Page Applications qui sont de plus en plus populaires. Le principe est de ne charger qu'une seule page HTML (souvent statique) depuis le serveur, puis de reposer intégralement sur des requêtes AJAX pour la navigation et l'interaction. L'avantage est que l'on peut réduire le nombre et la taille de ces requêtes, en se contentant des données dans leur expression la plus simple, c'est-à-dire dans un format sérialisé comme JSON ou XML.

Toutes ces nouveautés de plus en plus incontournables ont pour première conséquence de délocaliser toujours plus d'intelligence applicative côté JavaScript. Les développeurs ont alors dû s'adapter et inventer de nouveaux outils pour manipuler plus facilement le Document Object Model (DOM) et interagir avec la page en JavaScript. Vous connaissez probablement tous jQuery, la bibliothèque JavaScript la plus populaire qui s'est fait connaître pour sa fonction sélecteur quasi omnipotente. Aujourd'hui, je vous propose de passer au niveau supérieur en vous présentant tout ce qu'il y a à savoir sur le templating côté client.

II - Qu'est-ce que le templating ?

Les templates sont des modèles décrivant la manière dont les données sont composées pour former l'aspect final d'un document ou d'une partie d'un document. Dans le cas du Web, ils serviront donc à produire de manière descriptive et intuitive le HTML qui composera vos pages. Historiquement, les outils de templating travaillaient presque tous côté serveur. Certains mêmes étaient des composantes intégrales d'un langage. Ainsi vous connaissez probablement tous les balises <? ?> de PHP ou encore <% %> de JSP.

Exemple PHP

<h3>Auteur(s) du livre:</h3>
<ul>
<?
foreach ($authors as $name) {
echo "<li>$name</li>";
}
?>
</ul>

Exemple JSP

<h3>Auteur(s) du livre:</h3>
<ul>
<%
for (int i = 0; i < authors.length; ++i) {
%>
<li><%= authors[i] %></li>
<%
}
%>
</ul>

Tous les outils de templating s'utilisent à peu près de la même façon : on envoie le template d'un côté, les données de l'autre, et il en sort le HTML final de la vue.

III - Pourquoi délocaliser le templating côté client ?

Si j'ai parlé d'AJAX en introduction, c'est qu'il est une des raisons principales pour laquelle déplacer ce travail de templating du serveur vers le client peut être une bonne idée. Rien n'empêche de faire une requête AJAX et d'utiliser un templating côté serveur pour générer un fragment de HTML, puis l'envoyer au client pour l'injecter dynamiquement dans la page en JavaScript. Seulement le dynamisme apporté par AJAX est modéré par la durée de la requête, qui comprend la latence réseau et le temps de traitement. De plus, il se peut que certaines actions sur votre site entraînent une modification de la vue sans pour autant que notifier le serveur soit nécessaire. On se retrouve ainsi à devoir faire appel à JavaScript de temps à autre pour modifier la page. Dès lors, pourquoi ne pas franchir le pas et confier tout le templating à JavaScript ?

Modèle de données

var data = {
title : "Good Omens",
authors : [ "Terry Pratchett", "Neil Gaiman" ]
};

Template (bibliothèque EJS)

<h2><%= title %></h2>
<h3>Auteur(s) du livre:</h3>
<ul>
<% for(var i=0; i<authors.length; i++) { %>
<li><%= authors[i] %></li>
<% } %>
</ul>

Résultat

<h2>Good Omens</h2>
<h3>Auteur(s) du livre:</h3>
<ul>
<li>Terry Pratchett</li>
<li>Neil Gaiman</li>
</ul>

Le code ci-dessus est un template EJS (Embedded JavaScript). Il s'agit d'une bibliothèque JavaScript, d'à peine 10 KB, qui s'occupe de lire et d'interpréter les templates tels que celui-ci.

Hé, ce n'est pas très différent du templating serveur.

Hé non ! C'est tout dit la même chose J'ai choisi de vous montrer EJS, car sa syntaxe est volontairement destinée à ne pas brusquer les développeurs habitués à JSP et PHP. La différence majeure réside non pas dans la déclaration des templates, mais dans leur utilisation. Côté serveur, les outils de templating prennent naturellement la main au moment de générer des réponses aux requêtes HTTP reçues. Côté client par contre, vous avez le total contrôle de quand et comment faire appel à votre bibliothèque de templating.

Si vous n'êtes pas encore décidé, voilà un tableau synthétique des avantages et inconvénients du templating côté serveur ou côté client :

Templating

Côté serveur

Côté client

Avantages

Votre site peut toujours fonctionner sur les navigateurs avec JavaScript désactivé (moins de 1 % des requêtes d'après les statistiques de Yahoo en 2011). La logique de composition de vos vues n'est pas transmise au client. Si vous avez des choses à cacher, elles seront plus difficiles à trouver de l'extérieur.

Les requêtes peuvent être allégées en passant les données sous leur forme la plus simple « only Data on Wire ». Vous bénéficiez d'un contrôle accru de quand et comment vos templates sont utilisés. Votre templating peut toujours fonctionner lorsque la connexion est perdue.

Inconvénients

Le rendu des templates consomme des ressources serveur (généralement inférieures à celles utilisées par les requêtes BDD). Chaque utilisation d'un template implique une requête HTTP et un aller-retour client-serveur.

Certains navigateurs particulièrement obsolètes peuvent ne pas supporter la bibliothèque de templating (le support reste généralement très bon). Le temps de rendu peut varier selon le terminal client (bien que généralement très court et parfaitement négligeable).

IV - Le faux argument de la performance

Les progrès des navigateurs et des moteurs d'exécution JavaScript tendent à naturellement faire pencher la balance du côté client si l'on réfléchit en termes de performance pure. En effet, même si les templating serveurs resteront au niveau matériel et logiciel plus performants que leur équivalent client, le temps de rendu des templates reste largement inférieur à la latence réseau. Prenons un exemple concret : générer une liste de 10 000 livres et leurs auteurs.

Format HTML attendu :

<ol>
<li>
<h2>David Copperfield</h2>
<h3>Auteur(s) du livre:</h3>
<ul>
<li>Charles Dickens</li>
</ul>
</li>
...
</ol>

Format sérialisé JSON :

{"books":[{"title":"David Copperfield","authors":["CharlesDickens"]},...]}

Admettons que les informations pour un livre occupent en moyenne 120 caractères sous leur forme HTML et 60 sous leur forme JSON. La liste complète de 10 000 livres occupe donc 1,2 Mo en HTML et 600 ko sous forme JSON.

Après benchmark sur un smartphone de gamme moyenne, la bibliothèque de templating JavaScript la plus performante testée (Hogan.js) donne 200 ms de temps de rendu pour la liste de 10 000 éléments. Admettons que l'on dispose d'un serveur puissant ne croulant pas sous la charge et capable de générer cette même liste en deux fois moins de temps, grâce au matériel supérieur et à la précompilation des templates. Cela nous donne donc 100 ms de gagnées en temps de rendu du template en dépit de 600 ko de plus dans la requête. En supposant que ce même smartphone soit dans de bonnes conditions réseau et reçoive la 3 G à un débit moyen de 5 Mb/s, les 600 ko de plus prendront donc environ… une seconde de plus à arriver. Même avec la vitesse des réseaux actuels, le temps de rendu s'avère dix fois plus court que le temps de requête.

Cet exemple est très approximatif et hypothétique, mais il sert juste à rejeter le faux argument exposé au premier abord par les réfractaires du templating client-side selon qui le templating JavaScript n'est pas assez performant par rapport aux solutions serveur.

J'espère à présent vous avoir convaincu que déplacer le templating côté client présente un réel intérêt, et vous dispensera à l'avenir de « code spaghetti » pour modifier vos vues localement.

V - Tour d'horizon des bibliothèques de templating

Quand il s'agit de concevoir un outil de templating, tout le monde n'est pas d'accord sur la part de logique à mettre du côté vue (HTML) et la part de logique à mettre du côté modèle (JavaScript). Certains préfèrent la simplicité en utilisant des syntaxes très permissives voire en écrivant du code JS au sein du HTML. D'autres préfèrent les templates dits « logic-less », afin d'épurer le code des vues et de s'assurer une plus grande proximité entre le modèle de données et ce qui est affiché sur la page.

Question lisibilité, il est difficile de s'accorder. L'un rendra la logique de la vue plus explicite, l'autre mettra le HTML final de la vue en évidence. Il convient donc de choisir selon vos préférences et vos besoins. Néanmoins, la tendance générale est davantage tournée vers les templates logic-less comme le montrent les choix opérés pour Angular et Ember, deux des frameworks JavaScript les plus populaires du moment.

Si on trace un axe allant du plus au moins en quantité de logique côté template, et que l'on y place quelques outils de templating connus, voilà ce que ça donnerait (attention, ce graphe est issu de mon interprétation personnelle des choix faits pour chaque bibliothèque)

Nous n'allons pas tous les passer en revue. J'en ai sélectionné quatre qui représentent bien selon moi les différentes solutions existantes et leurs différences. Pour chacune, nous allons reprendre l'exemple de la liste de livres et comparer les implémentations. Voici les données que nous utiliserons :

Modèle de données

var data = [
{
title : "David Copperfield",
authors : [ "Charles Dickens" ]
},
{
title : "Romeo and Juliet",
authors : [ "William Shakespeare" ]
},
{
title : "Good Omens",
authors : [ "Terry Pratchett", "Neil Gaiman" ]
}
];

V-A - La vieille méthode : innerHTML ou jQuery.append

var output = "<ol>";

for(var i=0; i < data.length; i++){
var book = data[i];
output += "<li><h2>" + book.title + "</h2>"
+ "<h3>Auteur"+(book.authors.length>1 ? "s" : "") + "du livre:</h3>"
+"<ul>";
for(var j=0; j< book.authors.length; j++){
output += "<li>" + book.authors[j] + "</li>";
}
output += "</ul>";
}

output+="</ol>";
document.getElementById("result").innerHTML = output;

Presque tous les codeurs en JavaScript sont déjà passés par là. On construit simplement le HTML sous forme de String en y concaténant les données aux endroits désirés, avant de l'injecter dans le DOM avec la propriété innerHTML du conteneur à remplir. Il n'y a pas de template, le code logique est mélangé au code de la vue. Cette méthode est de loin la plus flexible, l'intégralité de la vue étant gérée au caractère près par votre code JavaScript. Mais c'est également la moins lisible et la moins maintenable, ce qui apporte vite son lot de difficultés pour les projets et les vues plus complexes. Heureusement, on a inventé les templates !

V-B - DOMjs

https://github.com/medikoo/domjs

Plutôt que de songer à créer une syntaxe spécifique pour les templates, certains préfèrent simplement déclarer de nouvelles fonctions pour rendre le code ci-dessus plus lisible. L'idée qu'a eue le créateur de DOMjs est de déclarer une fonction JavaScript pour chaque tag HTML permettant de générer l'élément HTML associé et son contenu à la demande. DOMjs est une bibliothèque en cours de développement, incomplète, mal documentée et certainement pas prête pour être utilisée en production, mais c'est un bon exemple de solution intermédiaire que l'on peut imaginer avant de faire appel à du vrai templating :

var template = function(){

var output = ol();
for(var i=0; i < data.length; i++){
var book = data[i];
var authorsList = ul();

for(var j=0; j< book.authors.length; j++){
authorsList( li(book.authors[j]) );
}

output(
li(
h2(book.title),
h3("Auteur"+(book.authors.length>1 ? "s" : "")+"du livre:"),
authorsList
)
);
}

};

document.getElementById("result").appendChild(domjs.build(template));

Le code est finalement assez proche de celui utilisant innerHTML mais en plus allégé. La différence majeure, cependant, réside dans le fait que l'on manipule des DOMElement plutôt que des String. On a donc la possibilité d'utiliser toutes les méthodes, propriétés et évènements JavaScript à notre disposition tels que setAttribute, onclick, dataset… Autrement dit une syntaxe plus riche et plus légère. Mais nous avons toujours du HTML-like perdu au milieu de notre JavaScript. Tâchons d'aller plus loin.

Dans le même genre :

- Jade: http://jade-lang.com/

V-C - John Resig micro templating

http://ejohn.org/blog/javascript-micro-templating/

Cette bibliothèque microscopique (moins de 1 ko) est un petit bijou de John Resig, que certains connaissent déjà pour être le créateur de jQuery. Il fournit simplement une fonction tmpl prenant en paramètre l'ID d'un template, et les données sous forme d'objet JavaScript.

<script type="text/html" id="books_template">
<ol>
<% for ( var i = 0; i < data.length; i++ ) { %>
<li>
<h2><%=data[i].title%></h2>
<h3>Auteur<% if(data[i].authors.length > 1){%>s<%}%> du livre:</h3>
<ul>
<% for ( var j = 0; j < data[i].authors.length; j++ ) { %>
<li><%=data[i].authors[j]%></li>
<% } %>
</ul>
</li>
<% } %>
</ol>
</script>

document.getElementById("result").innerHTML = tmpl("books_template", data);

Le template est défini par une balise script qui peut être placée n'importe où dans la page (mais pas dans le conteneur « result » dont le contenu va être écrasé avec innerHTML). Notez l'attribut type de la balise script. Il ne s'agit pas d'un attribut standard, simplement les navigateurs n'essaieront pas de l'interpréter comme du JavaScript puisqu'ils ne reconnaîtront pas le type.

La syntaxe des templates ne devrait pas déconcerter les développeurs habitués aux JSP. L'avantage de cette bibliothèque outre sa petite taille est la facilité avec laquelle on peut intercaler du JavaScript entre les nœuds HTML, apportant lisibilité et flexibilité à la logique de la vue. Cependant, il peut être difficile de discerner rapidement le HTML final rendu par le template. Et si on tâchait de réduire la quantité de logique côté template ?

Dans le même genre :

- Embedded JavaScript (EJS) : http://embeddedjs.com/

- doT: http://olado.github.io/doT/

V-D - mustache

https://github.com/janl/mustache.js/

mustache est la première syntaxe de templating abordée dans cet article que l'on pourrait qualifier de « logic-less ». En effet, seules des fonctions basiques comme les conditions ou les boucles sont permises au sein du template. Tout autre traitement plus complexe devra être fait au préalable en JavaScript avant d'envoyer les données au moteur de templating : c'est ce qu'on appelle le data preprocessing. Ce sont toutes les opérations qui vont venir s'intercaler entre le modèle de données initial et la vue. Dans notre exemple, on peut par exemple préprocesser la règle pluriel appliquée au label « Auteur(s) du livre ».

La syntaxe mustache est utilisée dans un grand nombre de langages différents. C'est pour ainsi dire une des références en matière de templating logic less, c'est pourquoi vous serez amenés à la retrouver dans beaucoup de bibliothèques de templating JS telles que handlebars, ICanHaz, ou avec quelques différences/ajouts comme pour Hogan ou Dust. Pour l'exemple, j'utiliserai ICanHaz qui permet d'externaliser vos templates facilement dans des balises script au sein de votre page.

Voilà ce cela que donne :

<div id="result"></div>
<script id="books_template" type="text/html">
<ol>
{{#books}}
<li>
<h2>{{title}}</h2>
<h3>Auteur{{#pluriel}}s{{/pluriel}} du livre:</h3>
<ul>
{{#authors}}
<li>{{.}}</li>
{{/authors}}
</ul>
</li>
</ol>
</script>

//Data preprocessing
for(var i=0; i < data.length; i++){
var book = data[i];
book.pluriel = (book.authors.length > 1);
}
//Template rendering
var html = ich.books_template({ books: data });

//HTML appending
document.getElementById("result").innerHTML = html;

Vous constaterez que le template est tout de suite beaucoup plus lisible. Néanmoins il a fallu d'abord préprocesser les données . Si dans cet exemple, c'est assez trivial, il arrive que cette étape soit beaucoup plus fastidieuse dans des templates plus complexes. Il revient à vous de décider si ce traitement est fait côté serveur ou côté client, et comment l'isoler du reste de votre code. Gardez toutefois à l'esprit qu'il peut être utile de disposer des mêmes données dans son modèle et sur la page, telles que les voient vos utilisateurs. Toute la logique que vous mettrez dans vos templates ne pourra pas être réutilisée ailleurs dans votre application. C'est pourquoi l'utilisation d'un template logic less peut au début vous apparaître comme une contrainte, mais finalement vous obliger à modulariser votre code et éviter les copier/coller : un bon point pour votre application !

Dans le même genre :

- Handlebars : http://handlebarsjs.com/

- Dust : http://akdubya.github.io/dustjs/

- Hogan : http://twitter.github.io/hogan.js/

V-E - PURE

http://beebole.com/pure/

Terminons par Pure qui comme son nom l'indique cherche à épurer au maximum les templates. Contrairement à JRMT et Mustache, il s'agit d'un templating basé sur le DOM : on associe les données à des éléments HTML et non en manipulant des String pour former le HTML final. Dans le cas de PURE, cette association de données aux nœuds HTML peut se faire de deux façons : soit simplement en utilisant l'attribut class ; soit en utilisant des sélecteurs plus complets pour décrire les liens données-DOM dans une hashmap appelée directive. Regardons le code, c'est bien plus parlant :

<div id="result">
<ol>
<li class="books">
<h2 class="title"></h2>
<h3 class="authorsLabel"></h3>
<ul>
<li class="authors"></li>
</ul>
</li>
</ol>
</div>

//Data preprocessing
for(var i=0; i < data.length; i++){
var book = data[i];
book.authorsLabel = "Auteur" + (book.authors.length > 1 ? "s" : "") + " du livre";
}

$p("#result").render(data);

Utiliser les classes pour définir les associations data-HTML nous oblige à ajouter des classes aux éléments HTML. Il y a un gros avantage et un gros inconvénient à cela. L'avantage, c'est que cela leur donne un sens explicite et facilite considérablement la lecture du DOM et des règles CSS qui lui sont associées. L'inconvénient, c'est que cela pose un risque de conflit avec des règles CSS existantes en mélangeant le templating avec la gestion du style. Ce qui fait que ce système de templating est plus intrusif que les autres, ce qui peut être gênant notamment lorsque l'intégrateur n'est pas la personne qui a fourni la maquette HTML et le design. C'est pourquoi l'auteur a imaginé le système de directives pour gérer les associations côté JavaScript et permettre au développeur d'utiliser les sélecteurs de son choix plutôt que d'imposer l'utilisation de classes.

var directive = {
'li.books': 'books',
'h2': 'title',
'h3': 'authorsLabel',
'li.authors': 'authors'
};

$p("#result").render(data, directive);

Dans le même genre :

- Transparency: http://leonidas.github.io/transparency/

VI - Quel templating choisir ?

Avant tout, si j'ai tenu à vous présenter quatre systèmes de templating très différents, c'est pour que vous puissiez vous forger votre propre opinion et choisir en toute connaissance de cause. Chaque approche a ses avantages et ses inconvénients. Mon choix personnel ? J'aime les templates très épurés et je crois beaucoup aux bénéfices du logic less et du templating DOM-based. Mais je n'ai pas trouvé d'outil de templating qui m'apporte totale satisfaction. Alors j'ai comme projet dans les cartons de développer ma propre bibliothèque de templating basée sur les data-attributes : logic-less, DOM-based, non intrusive. La syntaxe de KnockoutJS me plaît beaucoup, dommage que je ne puisse pas utiliser uniquement la partie templating de ce framework MVVM.

Je vous recommande de tester rapidement plusieurs bibliothèques qui vous plaisent au premier abord avant de faire votre choix. Et si vous hésitez encore, il existe ce site : http://garann.github.io/template-chooser/ qui vous permettra de trouver le système de templating qu'il vous faut en répondant à quelques questions.

VII - Aller plus loin

VII-A - Le data-binding

Vous connaissez AngularJS, Ember, KnockoutJS ? Tous ces frameworks JavaScript assez populaires en ce moment proposent quelque chose d'un peu plus sophistiqué que du templating : ils peuvent générer facilement du HTML avec des données JavaScript, mais aussi modifier ces données directement en fonction de la saisie de l'utilisateur dans le HTML ou encore mettre à jour automatiquement la vue lorsque les données changent côté modèle. Cette sorte de templating à double sens est couramment appelée data-binding.

On pourrait certainement considérer le data-binding comme l'évolution du templating. Et pour être utilisateur régulier d'AngularJS, j'ai pleinement conscience de tout le potentiel du data-binding. Seulement il n'est pas adapté à toutes les applications, mais plutôt à celles qui fonctionnent beaucoup sur le temps réel avec des mises à jour serveur et des saisies utilisateur fréquentes. Pour les autres, le rafraichissement automatique des vues peut être remplacé par un rappel manuel à la bibliothèque de templating sur une sous-partie d'un template ; et les saisies utilisateur peuvent être gérées de manière plus classique en définissant soi-même les EventListeners. Moins de magie, plus de contrôle, ce n'est parfois pas plus mal.

VII-B - Gérer l'internationalisation côté client

Beaucoup de sites utilisent les solutions de templating côté serveur pour gérer également la traduction du site en différentes langues selon l'utilisateur. Gérer l'internationalisation en JavaScript est également possible, bien que le sujet ne soit pas beaucoup abordé dans les bibliothèques de templating. Vous pouvez tout à fait faire cohabiter dans les réponses serveur vos données avec différents labels traduits dans la langue de l'utilisateur. En revanche ce n'est peut-être pas la solution optimale. En effet, il y a généralement beaucoup plus de texte à traduire que de données à afficher au sein d'une page. Cela pourrait entraîner une surcharge importante des réponses AJAX et une perte de performance.

Dans un de mes projets, j'ai imaginé une autre solution. Mon site est une Single Page Application comme décrit en introduction, et donc tout le HTML de mes pages passe par une fonction JavaScript avant d'être injecté dans le document. J'ai ajouté un traitement supplémentaire en JavaScript juste avant l'injection : tout le HTML est analysé avec une expression régulière pour identifier un certain pattern et remplacer les labels par l'équivalent traduit. Les traductions sont chargées préalablement au format JSON lors du chargement initial du site.

app.injectHTML = function(container, html){
var htmlTraduit = html.replace(/{LANG\.([\w\.]+)\}/g, function(match, label){
if(label in app.lang){
return app.lang[label];
} else {
console.warn("Label "+label+" not found in lang "+app.lang.name);
return "???";
}
});
$(container).html(html);
};

app.lang = {
"name": "FR",
"accueil.bienvenue": "Bonjour {{username}} !",
...
};

Ce qui est intéressant avec cette solution, c'est que ces labels traduits peuvent contenir d'autres marqueurs de template utilisés avec un autre outil de templating en aval (dans le cas présent, une syntaxe mustache). Cela donne pas mal de flexibilité dans le formatage des données selon la langue. La principale contrainte de cette solution est que l'on doit charger toutes les traductions au préalable. Le but est donc de trouver le meilleur moment pour envoyer les labels traduits sans que cela se ressente sur les performances.

Je ne prétends pas que cette solution soit la meilleure, et si vous avez d'autres idées n'hésitez pas à les faire partager dans les commentaires. Bien sûr, ce genre de mécanismes peut s'appliquer à d'autres choses que la gestion des langues : du chargement adaptatif selon le navigateur ou le type d'appareil par exemple…

VIII - Conclusion

Voilà, vous savez à présent tout du templating client. À présent, vous n'avez plus d'excuses pour écrire du JavaScript interminable et illisible quand il s'agit de générer du HTML. J'espère que cet article vous a été profitable, et je compte sur vous pour venir enrichir le sujet avec vos propres expériences.

IX - Remerciements et références

Merci à vermine ainsi qu'à Bovino pour leur relecture et leurs conseils avisés. Merci à Claude LELOUP et Philippe DUVAL pour leur relecture orthographique de qualité.