Couverture illustrée montrant un paysage calme, le titre intégré et un grand chemin qui se divise en plus petits chemins lumineux

Je travaille en développement web depuis longtemps. Quand j'ai commencé, la majorité de ce qu'on construisait était côté serveur. Comme beaucoup de gens, j'ai commencé avec du HTML statique et du JavaScript, puis je suis passé à PHP et aux applications basées sur des sessions.

En venant du monde des applications logicielles, le modèle du web m'a demandé un temps d'adaptation. L'idée que chaque chargement de page réinitialise essentiellement l'expérience, et qu'il faille reconstruire le contexte de l'utilisateur à chaque fois, me semblait inefficace au début. Mais c'était le modèle, et avec le temps j'ai appris à raisonner à l'intérieur de celui-ci. Plus tard, j'ai passé des années à bâtir des plateformes et des CMS sur mesure autour de cette façon de faire.

Plus récemment, comme beaucoup d'entreprises, nous avons commencé à nous éloigner de cette approche. Nous avons séparé le frontend du backend et construit des expériences côté client plus riches avec React et des single-page applications. Ce changement a apporté de vrais avantages. Les interfaces sont devenues plus dynamiques. Les interactions semblaient souvent plus rapides une fois l'application chargée. Les équipes ont aussi gagné une séparation plus claire entre la présentation et la logique d'affaires.

Mais ce changement a aussi modifié l'endroit où le travail se fait. Quand une plus grande partie de l'application s'exécute dans le navigateur, une plus grande part de la responsabilité se déplace vers l'appareil de l'utilisateur. Dans certaines situations, cela fonctionne bien. Dans d'autres, cela devient un problème. Tous les utilisateurs n'ont pas un portable rapide, un téléphone récent ou une connexion stable. Si le site semble lent, peu réactif ou visuellement instable, l'architecture peut paraître moderne tout en livrant une mauvaise expérience.

C'est en partie pour cela que certaines entreprises qui avaient poussé fortement les applications rendues côté client ont ensuite réintroduit davantage de rendu côté serveur. Ce n'est pas parce que l'approche précédente était automatiquement mauvaise. C'est parce qu'elles ont réalisé que l'endroit où le travail se fait compte autant que l'apparence moderne de la pile technologique.

Pour moi, c'est la manière la plus utile de regarder la performance : comme un problème de placement de charge. Certaines tâches appartiennent au serveur. D'autres au navigateur. Certaines peuvent attendre que le premier écran soit visible. D'autres ne devraient jamais bloquer l'utilisateur. Dès que j'ai commencé à regarder la performance frontend sous cet angle, la discussion m'a semblé plus utile que les débats habituels sur les frameworks.

Côté frontend en particulier, l'une des plus grandes contraintes est le main thread. C'est là qu'une grande partie de l'exécution JavaScript, de la coordination de l'interface et de la gestion des interactions se rencontrent. Quand trop de choses y arrivent en même temps, l'expérience commence à paraître lourde. Les boutons répondent avec retard. Le défilement devient moins fluide. Les saisies laguent. Même quand tout fonctionne techniquement, l'application ne donne plus une bonne impression.

La comparaison qui m'est venue est un pattern que nous utilisons depuis des années au backend : déléguer le travail. Côté serveur, quand quelque chose est coûteux ou non critique, on le déplace ailleurs. On le met en file, on le traite en parallèle, ou on le confie à un autre service. On n'insiste pas pour que chaque tâche se fasse dans le même chemin d'exécution si cela dégrade l'expérience.

La question est donc devenue : peut-on appliquer davantage cette logique dans le navigateur ? Les navigateurs nous donnent certains outils pour cela. Les Dedicated Web Workers permettent de déplacer certains calculs hors du main thread. Les Service Workers peuvent prendre en charge le cache, le hors ligne et certaines préoccupations au niveau réseau. Il existe aussi des worklets plus spécialisés pour des cas précis de rendu ou d'audio. Dans la bonne situation, ces outils peuvent aider à garder l'application visible plus réactive.

Sur papier, cela semble être un gain évident. Si une application navigateur fait trop de choses au même endroit, pourquoi ne pas sortir une partie du travail ?

La réponse est la même que dans la plupart des décisions d'architecture : parce que le compromis n'est pas gratuit. Déplacer du travail hors du main thread ajoute de la complexité. Il faut penser autrement à la communication, à l'état, au débogage, au support navigateur et à ce que le code a vraiment le droit d'exécuter dans ces environnements. Et cela ne règle pas tous les problèmes de performance. Par exemple, l'instabilité visuelle se traite généralement plus directement en réservant correctement l'espace et en conçevant des états de chargement stables, pas en introduisant des workers.

Mon équipe a regardé cette piste. Nous avons exploré si des workers pouvaient aider dans des parties significatives de notre application. Le concept était attirant, mais en pratique nous n'avons pas trouvé de cas où la complexité supplémentaire d'implémentation justifiait clairement le gain pour nos utilisateurs.

Cette conclusion me semble importante, parce qu'il est facile de confondre complexité disponible et complexité utile. Une bonne architecture ne consiste pas à utiliser des fonctionnalités avancées simplement parce qu'elles existent. Elle consiste à savoir quand la complexité supplémentaire va améliorer concrètement le produit, et quand elle ne fera que rendre le système plus difficile à comprendre et à maintenir.

Je crois quand même que cette façon de penser est sous-utilisée en frontend, non pas parce que chaque application a besoin de workers, mais parce que trop d'équipes traitent encore le navigateur comme si toute la logique devait naturellement passer dans un seul flux très occupé. Pour moi, le changement le plus important est conceptuel : la performance frontend moderne ne consiste pas seulement à livrer moins de JavaScript ou à choisir un framework plus récent. Elle consiste à être intentionnel sur l'endroit où le travail s'exécute, sur le moment où il s'exécute, et sur le fait de savoir si l'utilisateur devrait même le sentir.

Cela va au-delà des threads en arrière-plan. Cela inclut aussi le fait de différer les chargements de données non essentiels, de décider ce qui devrait être rendu côté serveur, de concevoir des états de chargement qui restent stables, et d'éviter les interfaces qui sautent pendant l'arrivée du contenu. Les utilisateurs n'ont pas besoin de comprendre l'architecture. Ils ont seulement besoin que le produit paraisse rapide, stable et fiable.

À partir du moment où on commence à raisonner en termes de placement de charge, ce pattern cesse d'être uniquement un sujet frontend. Il commence à apparaître dans d'autres parties de l'ingénierie aussi, parce que la question de fond reste la même : qu'est-ce qui devrait se passer ici, qu'est-ce qui devrait se passer ailleurs, et quel est le coût de cette séparation ?

Avec l'IA agentique qui devient une partie du développement quotidien, nous commençons à faire face à un problème d'orchestration semblable. Au début, tout se passe dans un contexte principal. Ensuite, les gens essaient de tout déléguer. Après cela, la maturité s'installe, et la vraie question devient : qu'est-ce qui devrait être délégué, quel contexte devrait partir avec, et à partir de quel moment le coût de coordination dépasse le gain ? Le médium change, mais le problème de jugement se ressemble. Que l'on parle d'architecture navigateur, de systèmes backend ou de flux de travail assistés par l'IA, un gros problème devient souvent plus gérable lorsqu'il est découpé en tâches plus petites et mieux placées. Mais la partie difficile n'est pas le découpage. La partie difficile est de décider ce qui vaut vraiment la peine d'être découpé.

Ce point de décision me semble devenir plus important avec le temps. À mesure que les outils s'améliorent, les équipes pourraient devenir plus enclines à expérimenter des décisions de placement de charge qui semblaient auparavant trop complexes ou trop coûteuses à poursuivre. Une partie de cela se verra peut-être en frontend, une autre au backend, et une autre encore dans les flux de travail assistés par l'IA. Je suis curieux de voir comment cela changera notre manière de construire dans les prochaines années, non pas parce que chaque système devrait devenir plus compliqué, mais parce que les équipes qui comprendront le mieux où le travail devrait se faire construiront probablement les expériences qui paraîtront les plus simples aux utilisateurs.

- Patrick