Chapitre 18
Chapitre 18 — Exercices
> 40 exercices pratiques classés par niveau pour valider et approfondir vos compétences front-end.
Chapitre 18 — 40 Exercices Pratiques
Niveau Débutant (Exercices 01–10)
HTML sémantique, CSS layout, JavaScript fondamentaux, Git
Exercice 01 — Page HTML Sémantique
Énoncé : Créez une page HTML complète structurée sémantiquement représentant un article de blog. La page doit inclure : un header avec navigation, un article principal avec titre, métadonnées (auteur, date), contenu texte, une image, une section de commentaires, et un footer.
Contraintes :
- Aucune feuille de CSS (structure uniquement)
- Utilisez uniquement des balises sémantiques HTML5 (
<header>,<main>,<article>,<section>,<nav>,<aside>,<footer>) - Pas de
<div>ou<span>sauf si absolument nécessaire - Texte d'exemple en français (lorem ipsum acceptable)
- Valide W3C
Critères de validation :
- Validation W3C passe sans erreur
- Les 7 balises sémantiques principales sont utilisées
- L'ordre de lecture au lecteur d'écran est logique
- Une image avec
altdescriptif est présente - Les commentaires ont un formulaire de soumission (non fonctionnel)
Durée estimée : 30 minutes
Exercice 02 — CV en HTML/CSS
Énoncé : Réalisez un CV au format HTML/CSS. Le CV doit contenir : photo, coordonnées, expériences professionnelles (3 minimum), formations, compétences avec barres de progression, et centres d'intérêt.
Contraintes :
- Flexbox obligatoire pour la mise en page
- Design responsive (mobile-first)
- Police Google Fonts (Roboto ou Inter)
- Palette de couleurs personnalisée via variables CSS
- Impressum : marges adaptées pour l'impression (media query
print)
Critères de validation :
- Layout responsive : 1 colonne < 600px, 2 colonnes ≥ 600px
- Les barres de compétences sont en CSS pur (pas de JS)
- Variables CSS correctement nommées (--color-primary, --spacing-md, etc.)
- L'impression (Ctrl+P) donne un rendu propre sans couleurs de fond
Durée estimée : 45 minutes
Exercice 03 — Grille CSS : Galerie d'Images
Énoncé : Créez une galerie d'images responsive utilisant CSS Grid. La galerie doit afficher 12 images avec des tailles variées, organisées en mosaïque type Pinterest.
Contraintes :
- CSS Grid uniquement (pas de Flexbox pour le layout global)
- Images de placeholder (picsum.photos ou équivalent)
- Au moins 3 breakpoints (mobile, tablette, desktop)
- Effet de survol avec overlay (titre, opacité)
- Lazy loading des images avec l'attribut
loading="lazy"
Critères de validation :
- La grille utilise
grid-template-areaspour la disposition - Le nombre de colonnes varie : 1 (mobile), 2 (tablette), 3-4 (desktop)
- Les images de tailles différentes s'adaptent sans déformation
- L'overlay apparaît en fondu au survol (transition CSS)
- Pas de JavaScript
Durée estimée : 1 heure
Exercice 04 — JavaScript : To-Do List
Énoncé : Développez une application To-Do List en JavaScript vanilla. Fonctionnalités : ajout de tâche, marquer comme terminée, suppression, filtres (toutes/actives/terminées), et compteur de tâches restantes.
Contraintes :
- Pas de frameworks ni de librairies (vanilla JS uniquement)
- Stockage local (localStorage)
- DOM manipulé proprement (pas de
innerHTMLpour les données utilisateur) - Accessibilité : les actions doivent être accessibles au clavier
- Design responsive sans librairie CSS
Critères de validation :
- Les tâches persistent après rechargement de la page
- Les 3 filtres fonctionnent (toutes/actives/terminées)
- Le compteur affiche le nombre de tâches actives
- La soumission par Enter fonctionne
- Un double-clic sur une tâche permet de l'éditer
Durée estimée : 1h30
Exercice 05 — Git : Collaboration Simulée
Énoncé : Simulez un workflow Git collaboratif. Créez un projet HTML simple, initialisez un dépôt Git, créez des branches, effectuez des commits, mergez avec et sans conflit, et rebasez.
Contraintes :
- Travail en local uniquement (pas de remote)
- Utilisez un dossier
git-exercice/en dehors du projet principal - Script bash des commandes à fournir en solution
- Commit message conventionnel (Conventional Commits)
Étapes obligatoires :
git init+ premier commit surmain(index.html vide)- Création de branche
feature/header(3 commits) - Création de branche
feature/footer(2 commits) - Merge de
feature/footersurmain - Création d'un conflit intentionnel sur
index.html - Résolution du conflit
- Rebase de
feature/headersurmain git log --graphpour visualiser l'historique
Critères de validation :
- L'historique final montre les 3 branches avec merge et rebase
- Le conflit est résolu avec les deux modifications conservées
- Les messages de commit suivent le format
type(scope): description - Le script est reproductible (effacer et ré-exécuter)
Durée estimée : 1 heure
Exercice 06 — Formulaire avec Validation
Énoncé : Créez un formulaire d'inscription complet avec validation en JavaScript. Champs : nom, email, mot de passe, confirmation, date de naissance, pays (select), et conditions d'utilisation (checkbox).
Contraintes :
- Validation en temps réel (au fur et à mesure de la saisie)
- Messages d'erreur spécifiques (pas de message générique)
- Validation email par regex (pas de pattern HTML5 uniquement)
- Force du mot de passe indiquée visuellement
- Soumission AJAX simulée (Promise avec setTimeout)
- Accessibilité ARIA :
aria-invalid,aria-describedby,role="alert"
Critères de validation :
- Les erreurs s'affichent/effacent en temps réel pendant la frappe
- Le bouton de soumission est désactivé tant que le formulaire est invalide
- Les regex sont correctes : email valide, mot de passe (8+ car, 1 maj, 1 chiffre, 1 spécial)
- Le feedback de force du mot de passe a 3 niveaux (faible, moyen, fort)
- La soumission montre un loader puis une confirmation
Durée estimée : 2 heures
Exercice 07 — Landing Page avec Animations CSS
Énoncé : Créez une landing page pour un produit fictif ("Nova — Assistant IA"). La page doit contenir : hero section, features (3 cartes), témoignages (carrousel), pricing (3 colonnes), et footer.
Contraintes :
- Animations CSS au scroll (intersection observer non autorisé)
- Utilisation de
@keyframesettransition - Transformations 3D pour les cartes (perspective)
- Variables CSS pour le thème
- Performance :
will-change,transform/opacityuniquement
Critères de validation :
- Les animations se déclenchent à l'apparition dans le viewport (via classe
.visible) - Les cartes de features ont un effet de survol 3D
- Le carrousel de témoignages défile automatiquement avec
@keyframes - Le pricing a 3 colonnes avec mise en avant de l'offre "Pro"
- Aucun JavaScript pour les animations (JS uniquement pour l'intersection observer)
Durée estimée : 2 heures
Exercice 08 — API Fetch : Dashboard Météo
Énoncé : Créez une application météo qui affiche la météo actuelle et les prévisions à 5 jours pour une ville saisie par l'utilisateur.
Contraintes :
- API gratuite : Open-Meteo (pas de clé API nécessaire) ou WeatherAPI
- Fonctions asynchrones avec
async/await - Gestion des erreurs : ville inexistante, réseau, timeout
- Icônes météo (SVG inline ou emoji)
- Graphique des températures en CSS (barres verticales)
Critères de validation :
- La recherche fonctionne par nom de ville
- Les données actuelles (température, humidité, vent, description) sont affichées
- Les prévisions 5 jours sont visibles avec min/max
- Un indicateur de chargement est présent
- Les erreurs sont affichées proprement (pas de console.log)
Durée estimée : 2 heures
Exercice 09 — Modules ES6 : Bibliothèque de Calcul
Énoncé : Créez une bibliothèque de fonctions mathématiques organisée en modules ES6. Exportez des fonctions, importez-les dans un fichier principal, et démontrez leur utilisation dans une interface simple.
Contraintes :
- Modules ES6 avec
export/import - Minimum 4 modules :
arithmetic.js,statistics.js,geometry.js,formatters.js - Utilisation de
import.meta.urlpour les chemins dynamiques - Arbres d'import avec dépendances entre modules
- Pas de bundler (navigateur avec
type="module")
Critères de validation :
- Chaque module exporte au moins 3 fonctions
- Le module
statistics.jsimporte depuisarithmetic.js - Le fichier
main.jsimporte les 4 modules - Une interface HTML simple (input/output) teste chaque fonction
- Les imports circulaires sont évités
Durée estimée : 1h30
Exercice 10 — Accessibilité : Audit et Correction
Énoncé : Prenez la page HTML de l'exercice 01 et corrigez-la pour atteindre le niveau AA des WCAG 2.2. Auditez avec axe DevTools, Lighthouse, et manuellement (clavier, lecteur d'écran).
Contraintes :
- Rapport Lighthouse Accessibilité ≥ 95
- axe DevTools : 0 violations critiques/sérieuses
- Navigation clavier complète (Tab, Enter, Escape)
- Contraste des couleurs ≥ 4.5:1 (texte normal)
- Structure de titres hiérarchique (h1 → h2 → h3)
- Landmarks ARIA corrects
Critères de validation :
- Rapport d'audit initial et final fournis
- Tous les éléments sont accessibles au clavier
- Les images décoratives ont
aria-hidden="true" - Les formulaires ont des
<label>explicites - Le
langattribute est correct - Les sauts de navigation (skip links) sont présents
Durée estimée : 1h30
Niveau Intermédiaire (Exercices 11–20)
React hooks, TypeScript generics, API calls, testing
Exercice 11 — Compteur avec useReducer
Énoncé :
Implémentez un compteur React utilisant useReducer avec des actions typées : increment, decrement, reset, setValue, incrementByAmount, et undo.
Contraintes :
- TypeScript strict
- Actions typées avec discriminated unions
- Historique des 10 dernières actions (undo)
- Deux boutons + et - , un champ input pour setValue
- Touche Escape pour reset
Critères de validation :
- Le reducer est une fonction pure testée unitairement
- L'historique undo fonctionne (y compris undo après undo)
- setValue accepte les nombres négatifs (mais pas NaN)
- Le type
Actionest untype(pas uneinterface) action.typeest correctement discriminé dans le switch
Durée estimée : 1h30
Exercice 12 — TypeScript Generics : Repository Pattern
Énoncé :
Créez une classe générique Repository<T> qui implémente les opérations CRUD avec stockage en mémoire. Étendez-la avec UserRepository et ProductRepository.
Contraintes :
- Contrainte de type :
T extends { id: string } - Méthodes :
findAll,findById,create,update,delete - Validation optionnelle via generic constraint
- Utilisation de
Partial<T>,Pick<T>,Omit<T>dans les signatures - Tests unitaires avec Vitest
Critères de validation :
Repository<User>fonctionne avecUser = { id: string, name: string, email: string }Repository<Product>fonctionne avecProduct = { id: string, title: string, price: number }updateacceptePartial<T>(mise à jour partielle)createretourne l'entité créée avec un ID auto-généré- Les types sont inférés sans annotations redondantes
Durée estimée : 2 heures
Exercice 13 — Custom Hook : useLocalStorage
Énoncé :
Créez un hook React useLocalStorage<T> qui synchronise un état avec localStorage, avec gestion des erreurs de sérialisation et de quota dépassé.
Contraintes :
- TypeScript avec générique
T - Gestion des erreurs de JSON.parse (fallback vers defaultValue)
- Gestion de quota Exceeded (try/catch dans le setter)
- Versioning des données (migration si le format change)
- Synchronisation entre onglets (storage event)
- Valeur par défaut si la clé n'existe pas
Critères de validation :
- Le hook persiste les données au rechargement
- Si localStorage contient du JSON invalide, le fallback s'applique
- Si le quota est dépassé, une erreur est loggée sans crash
- Si un autre onglet modifie la valeur, le hook se met à jour
- Le hook expose
removeetclearen plus de get/set
Durée estimée : 2 heures
Exercice 14 — Appel API avec React Query
Énoncé : Créez une application de liste de posts avec React Query (TanStack Query). Fonctionnalités : liste paginée, détail d'un post, création, édition, et suppression avec mutations.
Contraintes :
- API : JSONPlaceholder (ou équivalent)
- Pagination avec
useInfiniteQueryoukeepPreviousData - Mutations avec invalidation de cache optimiste
- Loading et error states pour chaque opération
- Retry automatique configurable (3 tentatives)
Critères de validation :
- La liste paginée charge 10 posts par page avec navigation
- Le cache est invalidé après création/suppression
- L'optimistic update rollback si la mutation échoue
- Les states loading/error/success sont correctement affichés
- Les données sont pré-fetchées au survol du lien de détail
Durée estimée : 2h30
Exercice 15 — Tests Unitaires avec Vitest
Énoncé :
Écrivez des tests unitaires complets pour un hook useCounter et pour une fonction utilitaire formatCurrency.
Contraintes :
- Vitest comme test runner
- Couverture de code ≥ 90%
- Tests de cas nominaux, limites, et erreurs
- Mock de
Intl.NumberFormatpour les tests de formatCurrency - Tests de rendu React (Testing Library) pour le hook
Critères de validation :
useCounter: test initial value, increment, decrement, reset, max/min limitsformatCurrency: test différents formats (EUR, USD, JPY), valeurs négatives, grands nombres- Les mocks sont restaurés après chaque test (
afterEach) - Les tests sont nommés clairement (describe/it)
- Coverage ≥ 90% confirmé par Vitest
Durée estimée : 2 heures
Exercice 16 — Formulaire avec React Hook Form
Énoncé : Créez un formulaire multi-step (3 étapes) avec React Hook Form et Zod pour la validation. Étapes : Informations personnelles → Adresse → Récapitulatif et soumission.
Contraintes :
- React Hook Form avec TypeScript
- Schéma de validation Zod
- Champs : nom, email, téléphone, rue, ville, code postal, pays
- Navigation entre étapes avec validation avant de passer à l'étape suivante
- Résumé modifiable avant soumission finale
Critères de validation :
- La validation Zod bloque le passage à l'étape suivante
- Les données persistent entre les étapes (même en revenant en arrière)
- Le résumé final affiche toutes les données
- Au moins 3 rules customs Zod (email valide, téléphone français, code postal)
- Le formulaire est accessible (labels, erreurs aria)
Durée estimée : 2h30
Exercice 17 — Composant Carrousel Accessible
Énoncé : Créez un composant Carrousel React réutilisable avec navigation infinie et contrôle clavier complet.
Contraintes :
- TypeScript + React
- Props :
items: T[],renderItem: (item: T) => ReactNode,autoPlay?: boolean,interval?: number - Navigation : flèches, dots, swipe tactile
- Accessibilité :
role="region",aria-roledescription="carousel",aria-label - Pause au survol et au focus
- Boucle infinie (pas de fin)
Critères de validation :
- Les props génériques sont correctement typées
- Le focus est piégé dans le carrousel actif (Tab ne sort pas)
- Les contrôles clavier : Flèche Gauche/Droite, Home/End
- Le défilement automatique se met en pause au survol
- Le défilement est fluide (CSS scroll-behavior ou animation)
Durée estimée : 2h30
Exercice 18 — Contexte d'Authentification
Énoncé : Créez un système d'authentification React complet avec Context API. Fonctionnalités : login, logout, inscription, refresh token, et protected routes.
Contraintes :
AuthProvideravec Context- TypeScript :
User,AuthState,AuthContext useAuthhook custom avec type guardProtectedRoutecomposant avec redirect- Token stocké en mémoire + refresh token en httpOnly cookie (simulé)
- Role-based access (
admin,user,guest)
Critères de validation :
useAuthlance une erreur si utilisé hors du ProviderProtectedRouteredirige vers/loginsi non authentifié- Le refresh token est appelé automatiquement à l'expiration
- Les rôles sont vérifiés :
RequireRole="admin"bloque les utilisateurs - Le contexte n'expose pas les méthodes sensibles (ex: setToken)
Durée estimée : 2 heures
Exercice 19 — Pagination avec Recherche
Énoncé :
Créez un hook usePaginatedQuery qui encapsule la logique de pagination, filtrage, et recherche pour une liste d'éléments.
Contraintes :
- API : SWAPI (Star Wars API) ou équivalent
- Paramètres :
page,search,sortBy,sortOrder - Debounce de la recherche (300ms)
- Query string synchronisée avec l'URL (useSearchParams)
- Pré-chargement de la page suivante
Critères de validation :
- Les paramètres sont persistés dans l'URL
- La recherche est debouncée (pas d'appel API à chaque frappe)
- Les données de la page suivante sont pré-chargées en arrière-plan
- Le changement de tri réinitialise la pagination
- L'historique du navigateur (back/forward) est supporté
Durée estimée : 2h30
Exercice 20 — Tests d'Intégration avec MSW
Énoncé : Écrivez des tests d'intégration pour une application React qui affiche une liste de tâches, avec MSW (Mock Service Worker) pour intercepter les appels API.
Contraintes :
- MSW (v2) avec handlers typés
- Vitest + Testing Library
- Tests : chargement, succès, erreur, empty state
- Scénario : ajout et suppression de tâche
- Pas de mock manuel des fetch/axios
Critères de validation :
- Les handlers MSW sont dans un fichier
mocks/handlers.ts - Le test vérifie l'affichage du loader, puis des données
- L'ajout de tâche mocké retourne la tâche avec un ID généré
- La suppression met à jour la liste sans re-fetch
- Les erreurs réseau retournent un message d'erreur approprié
Durée estimée : 2h30
Niveau Avancé (Exercices 21–30)
Performance, architecture, custom hooks, SSR
Exercice 21 — Virtual Scroll
Énoncé :
Implémentez un composant VirtualList<T> qui n'affiche que les éléments visibles dans le viewport, avec défilement fluide de 10 000 éléments.
Contraintes :
- Hauteur fixe des items configurable via
itemHeightprop - Taille totale calculée pour la barre de défilement
- Buffer de 3 items au-dessus et en-dessous du viewport
- Pas de librairie externe de virtualisation
- Support du clavier (Flèche Haut/Bas)
Critères de validation :
- 10 000 éléments rendus → seulement ~15 nœuds DOM
- Le défilement est fluide (60fps)
- La position du scroll est maintenue après remplacement des données
- Les éléments dynamiques (hauteur variable) sont gérés via mesure après rendu
- Les éléments sont recyclés (pas de création/suppression, juste mise à jour)
Durée estimée : 3 heures
Exercice 22 — Web Worker : Traitement d'Image
Énoncé : Créez une application de traitement d'images utilisant un Web Worker pour appliquer des filtres (noir et blanc, sépia, flou gaussien) sans bloquer le thread principal.
Contraintes :
- Canvas API pour la manipulation des pixels
- Web Worker dédié pour le traitement
- Transfert d'ImageData avec
transferable objects - Barre de progression du traitement
- Comparaison de performance (avec/sans Worker)
Critères de validation :
- L'interface reste réactive pendant le traitement (boutons cliquables)
- Les filtres sont appliqués correctement (matrices de convolution)
- La progression est affichée en temps réel
- Le transfert utilise
postMessageavec transferList - Le benchmark montre 0ms de blocage UI avec Worker vs >500ms sans
Durée estimée : 3 heures
Exercice 23 — Custom Hook : useWebSocket
Énoncé :
Créez un hook useWebSocket avec reconnexion automatique, souscription par événement, et file d'attente de messages pendant la déconnexion.
Contraintes :
- TypeScript avec types génériques pour les messages
useRefpour la connexion (pas de re-rendu)- Exponential backoff : 1s, 2s, 4s, 8s... max 30s
- File d'attente FIFO (max 50 messages)
- Souscription :
socket.on('event', callback)/socket.off('event', callback) - Ping/pong keepalive toutes les 30s
Critères de validation :
- La reconnexion s'arrête après 5 échecs consécutifs
- Les messages envoyés pendant la déconnexion sont mis en file d'attente
- Les callbacks sont nettoyés au unmount
- Le ping/pong évite la déconnexion du proxy/load balancer
- Les souscriptions multiples au même événement sont supportées
Durée estimée : 3 heures
Exercice 24 — Architecture : Micro-frontends Module Federation
Énoncé : Configurez une architecture micro-frontends avec Webpack Module Federation : trois applications indépendantes (Header, Dashboard, Settings) intégrées dans un shell.
Contraintes :
- Module Federation Plugin (Webpack 5)
- Shell (host) : routing, auth, layout
- Header (remote) : navigation, profil utilisateur
- Dashboard (remote) : widgets métier
- Settings (remote) : formulaire de configuration
- Partage de bibliothèques (React, MUI/Chakra)
Critères de validation :
- Chaque micro-frontend est déployable indépendamment
- Le shell hydrate les remotes sans duplication de React
- La communication inter-apps utilise un event bus personnalisé
- Le partage de styles est cohérent (design tokens)
- Les routes sont lazy-loadées
Durée estimée : 4 heures
Exercice 25 — Server-Side Rendering avec Next.js
Énoncé : Créez une application Next.js (App Router) avec SSR, ISR, et SSG. Pages : blog (SSG + ISR), profil utilisateur (SSR), dashboard protégé (SSR + auth), et page statique.
Contraintes :
- Next.js 14+ App Router
- Blog :
generateStaticParams+revalidate(ISR) - Profil :
dynamic = 'force-dynamic'+cookies() - Dashboard : middleware d'authentification
- Loading states avec
loading.tsx - Error boundaries avec
error.tsx
Critères de validation :
- La page blog est buildée statiquement puis régénérée toutes les 60s
- Le profil utilisateur charge les données à chaque requête
- Le middleware redirige vers
/loginsi pas de session - Le loading state est visible avant l'hydratation
- Les erreurs API sont catchées par l'error boundary
Durée estimée : 3 heures
Exercice 26 — React Query + WebSocket : Dashboard Temps Réel
Énoncé : Créez un dashboard temps réel qui combine React Query (initial data fetch) et WebSocket (mises à jour push) pour des métriques en direct.
Contraintes :
- React Query pour le chargement initial et le cache
- WebSocket pour les mises à jour incrémentales
- Graphiques en temps réel (Chart.js, D3, ou Recharts)
- Cache React Query mis à jour à la réception WebSocket
- Reconnexion WebSocket avec gestion du cache stale
Critères de validation :
- Les données initiales viennent de React Query (avec suspense)
- Les mises à jour WebSocket patch les données sans re-fetch
- Le graphique s'anime lors des nouvelles données
- Pendant la reconnexion, React Query sert les données en cache
- Le status de connexion WebSocket est affiché (connecté/déconnecté)
Durée estimée : 3h30
Exercice 27 — Optimisation : Bundle Splitting et Lazy Loading
Énoncé : Optimisez une application React avec React.lazy, Suspense, et analyse du bundle pour réduire la taille initiale de 70%.
Contraintes :
React.lazy+Suspensepour le code-splitting par routewebpack-bundle-analyzerouvite-plugin-visualizer- Préchargement stratégique :
prefetchau survol,preloadpour les routes critiques - Page cible : bundle initial < 100KB (gzippé)
- Composants lourds (éditeur de texte, graphiques) chargés à la demande
Critères de validation :
- Analyse avant/après montrant la réduction
- Bundle initial < 100KB gzippé
- Les chunks sont nommés explicitement (
/* webpackChunkName: "editor" */) - Le préchargement au survol est visible dans le Network tab
- Aucun flash/loading state bizarre pendant le chargement asynchrone
Durée estimée : 2h30
Exercice 28 — Tests de Performance avec Lighthouse CI
Énoncé : Configurez Lighthouse CI sur un projet React existant pour auditer automatiquement les performances, l'accessibilité, et les bonnes pratiques à chaque PR.
Contraintes :
- Lighthouse CI configuré dans GitHub Actions
- Assertions : Performance ≥ 90, Accessibility ≥ 95, SEO ≥ 95
- Budget de performance : LCP < 2.5s, TBT < 200ms, CLS < 0.1
- Rapport détaillé avec captures d'écran des audits échoués
- Comparaison avec la branche de base (main)
Critères de validation :
- Le job CI lance Lighthouse sur 3 pages (accueil, article, contact)
- Les assertions échouent si les scores sont en dessous des seuils
- Le rapport est uploadé en artefact
- Les métriques Web Vitals sont collectées
- Le budget de performance bloque le merge si dépassé
Durée estimée : 2 heures
Exercice 29 — Architecture : Clean Architecture en Front-end
Énoncé : Structurez une application React selon les principes de Clean Architecture : séparation en couches (domain, application, infrastructure, presentation) avec injection de dépendances.
Contraintes :
- Pas de dépendance directe entre la présentation et l'infrastructure
- Domain layer : entités, value objects, repository interfaces
- Application layer : use cases, DTOs
- Infrastructure layer : implémentations concrètes (API, localStorage, IndexedDB)
- Presentation layer : composants React, hooks
- Injection de dépendances via un container (IoC) ou props
Critères de validation :
- Changer d'API (REST → GraphQL) ne change que l'infrastructure layer
- Les use cases sont testables sans DOM
- Les entités sont des classes TS pures (pas de dépendances framework)
- Le data flow est unidirectionnel : UI → UseCase → Repository → API
- Les DTOs sont transformés en entités dans le application layer
Durée estimée : 4 heures
Exercice 30 — CI/CD Pipeline Complet
Énoncé : Créez un pipeline CI/CD complet avec GitHub Actions : lint, typecheck, tests, build, déploiement preview (PR) et production (main).
Contraintes :
- GitHub Actions workflow YAML
- Cache des dépendances (npm/yarn/pnpm)
- Matrix de tests (Node 18, 20, 22)
- Jobs parallélisés (lint + test en parallèle, build après)
- Déploiement preview sur Vercel/Netlify
- Notification Slack/Discord en cas d'échec
Critères de validation :
- Le pipeline s'exécute en moins de 5 minutes
- Les jobs sont parallélisés efficacement
- Le cache réduit le temps d'install à < 10s
- La PR a un commentaire avec le lien de preview
- Le déploiement production nécessite un tag de release (
v*)
Durée estimée : 3 heures
Niveau Expert (Exercices 31–40)
Micro-frontends, WebAssembly, monorepo, design system
Exercice 31 — Micro-frontends : Event Bus et Communication
Énoncé : Implémentez un event bus typé pour la communication entre micro-frontends, avec support de l'isolation et de la sécurité.
Contraintes :
- TypeScript : EventBus<T> avec types d'événements stricts
- Pattern : publish/subscribe avec filtrage par namespace
- Isolation : chaque micro-frontend a son namespace
- Bridge entre window.postMessage et l'event bus pour cross-origin
- Sécurité : validation des origin, throttling des événements
- DevTools : logging des événements échangés
Critères de validation :
events.on('dashboard:user-updated', handler)fonctionne- Les événements cross-origin passent par postMessage avec validation d'origin
- Un micro-frontend malveillant ne peut pas écouter les événements d'un autre namespace
- Le throttling limite à 60 événements par seconde
- Les DevTools affichent un log structuré de tous les événements
Durée estimée : 3h30
Exercice 32 — WebAssembly : Traitement d'Image avec Rust/WASM
Énoncé : Créez un module WASM en Rust (via wasm-pack) qui applique un filtre de convolution sur une image, et intégrez-le dans une application React.
Contraintes :
- Rust + wasm-pack pour la compilation WASM
- wasm-bindgen pour l'interopérabilité JS↔Rust
- Fonction Rust :
apply_convolution(input: &[u8], width: u32, height: u32, kernel: &[f32]) -> Vec<u8> - Benchmark comparatif JS vs WASM
- Gestion des erreurs Rust (panic → JS)
Critères de validation :
- Le filtre WASM est 3-5x plus rapide que l'équivalent JS
- L'image traitée est correcte (mêmes pixels que la version JS)
- La mémoire WASM est libérée après traitement
- Les panics Rust sont catchés en JS (try/catch)
- Le build wasm-pack génère les types TypeScript
Durée estimée : 4 heures
Exercice 33 — Monorepo avec Nx
Énoncé : Configurez un monorepo Nx avec partage de code entre plusieurs applications (web, mobile, admin) et librairies partagées.
Contraintes :
- Nx workspace (pnpm/yarn)
- 3 apps :
web(React),mobile(React Native),admin(React) - 5 libs :
ui(design system),shared(types/utils),api(API client),auth,i18n - Task orchestration : dépendances entre libs
- Cache distant (Nx Cloud ou équivalent)
- Affected commands dans la CI
Critères de validation :
nx graphmontre les dépendances correctesnx test webteste web + ses dépendances- La CI ne build/lint/test que les projets affectés
- Le cache distant est fonctionnel (second build < 1s)
- Les libs sont versionnées avec semantic-release
Durée estimée : 4 heures
Exercice 34 — Design System avec Storybook
Énoncé : Créez un design system complet avec Storybook, incluant 10 composants, des tokens de design, et une documentation exhaustive.
Contraintes :
- Storybook 7+ avec React + TypeScript
- 10 composants : Button, Input, Select, Modal, Table, Badge, Tooltip, Card, Avatar, Spinner
- Design tokens : couleurs, typographie, spacing, breakpoints, shadows
- Chaque composant a : stories (5+ variants), docs, tests d'interaction
- Accessibilité : axe-core addon, WCAG AA
Critères de validation :
- Les tokens sont des variables CSS + objets TS
- Les stories couvrent : default, disabled, loading, error, custom
- Les tests d'interaction (play function) vérifient le comportement
- Le dark mode est supporté (via class ou data-theme)
- Le build Storybook est déployable statiquement
Durée estimée : 5 heures
Exercice 35 — Module Fédéré : Shared State et Routing
Énoncé : Étendez l'exercice 24 avec un state partagé entre micro-frontends et un routing distribué.
Contraintes :
- Module Federation avancé
- Shared store : Zustand ou Redux avec slice isolation
- Routing distribué : chaque remote déclare ses routes dans le shell
- Lazy loading des remotes avec loading state
- Error boundary par remote (un remote qui crash n'affecte pas les autres)
- Versioning des remotes (compatible semver)
Critères de validation :
- Le store partagé est typé et isolé par namespace
- Les routes sont enregistrées dynamiquement par chaque remote
- Si le remote Dashboard crash, le Header continue de fonctionner
- La navigation entre les routes des différents remotes est fluide
- Le versioning permet de déployer différentes versions des remotes
Durée estimée : 5 heures
Exercice 36 — WebAssembly : Port d'une Librairie C
Énoncé : Portez une petite librairie C existante (ex: une librairie de compression simple) vers WebAssembly avec Emscripten, et créez une interface React.
Contraintes :
- Emscripten (emcc) pour la compilation C → WASM
- Wrapper JavaScript pour l'API C
- Module WASM chargé asynchrone avec progress
- Gestion de la mémoire manuelle (malloc/free)
- Comparaison de taille : .wasm < 50KB
Critères de validation :
- La fonction C est appelable depuis JS avec des paramètres typés
- La mémoire allouée en C est libérée correctement
- Le chargement asynchrone montre un indicateur de progression
- Le binaire WASM final fait moins de 50KB
- La fonction s'exécute sans fuite mémoire vérifiable
Durée estimée : 5 heures
Exercice 37 — Architecture : Event Sourcing en Front-end
Énoncé : Implémentez un système d'event sourcing côté client : chaque action utilisateur est un événement immutable, stocké dans IndexedDB, avec rejeu possible.
Contraintes :
- Event sourcing pattern : event store, projector, read model
- IndexedDB pour le stockage des événements avec Dexie.js
- Rejeu : possibilité de rejouer tous les événements pour reconstruire l'état
- Time travel : navigation dans l'historique des événements
- Snapshotting : création périodique de snapshots pour performance
- Undo/Redo basé sur les événements
Critères de validation :
- Chaque événement a : id, type, payload, timestamp, version
- Le projector met à jour le read model à partir des événements
- Le rejeu de 1000 événements prend < 100ms
- Le time travel permet de visualiser l'état à n'importe quel moment
- Les snapshots sont créés tous les 50 événements
Durée estimée : 5 heures
Exercice 38 — Performance : Web Vitals et Core Web Vitals
Énoncé : Auditez et optimisez une application React pour atteindre des scores Core Web Vitals parfaits (LCP < 1.5s, FID < 50ms, CLS < 0.05).
Contraintes :
- Optimisation LCP : preload des images critiques, optimisation du TTFB
- Optimisation FID/INP : code splitting, idle callbacks, lazy handlers
- Optimisation CLS : dimensions explicites, font-display: swap, skeleton screens
- Monitoring : web-vitals library + analytics (GA4/Plausible)
- Rapport Lighthouse ≥ 98 sur mobile
Critères de validation :
- LCP < 1.5s (simulated throttling)
- TBT < 100ms (simulated throttling)
- CLS < 0.05 (simulated throttling)
- Le rapport Lighthouse est ≥ 98 sur mobile
- Les métriques sont envoyées à un endpoint d'analytics
Durée estimée : 4 heures
Exercice 39 — API Gateway : BFF Pattern
Énoncé : Créez un Backend For Frontend (BFF) qui agrège plusieurs APIs backend (REST, GraphQL) et sert une API adaptée au front-end.
Contraintes :
- Node.js + Express ou Hono.js
- Agrégation : appels parallèles avec Promise.all
- Transformation : mapping des données au format attendu par le front
- Cache : in-memory cache avec TTL configurable
- Rate limiting : throttle par IP utilisateur
- Sécurité : validation des entrées, CORS, CSP headers
Critères de validation :
- Le BFF agrège 2 APIs backend en une seule réponse
- Le cache réduit les appels redondants (hit ratio > 50%)
- Le rate limiting bloque après 100 requêtes/minute
- Les headers de sécurité sont présents (CSP, X-Frame-Options)
- Le BFF est testé avec Supertest ou équivalent
Durée estimée : 4 heures
Exercice 40 — Full Stack : Application Complete
Énoncé : Créez une application full-stack complète (front-end React + BFF Node.js) avec authentification, CRUD, tests, CI/CD, et déploiement.
Contraintes :
- Monorepo (pnpm workspaces ou Nx)
- Front : React + TypeScript + Vite + TanStack Query
- Back : Hono.js + Prisma + SQLite (ou PostgreSQL)
- Auth : JWT avec refresh token
- Tests : Vitest (unit) + Playwright (E2E)
- CI/CD : GitHub Actions + Docker
- Documentation : README + ADR
Critères de validation :
- L'application est dockerisée et s'exécute avec
docker compose up - Les tests unitaires couvrent ≥ 80% du code
- Les tests E2E Playwright couvrent le parcours utilisateur complet
- Le pipeline CI s'exécute en < 10 minutes
- La documentation inclut ADR et diagramme d'architecture
Durée estimée : 8 heures
Récapitulatif
| Niveau | Exercices | Durée totale | Compétences clés |
|---|---|---|---|
| Débutant | 01–10 | ~10h | HTML sémantique, CSS (Flexbox/Grid), JS DOM, Git |
| Intermédiaire | 11–20 | ~15h | React hooks, TypeScript, API, testing |
| Avancé | 21–30 | ~20h | Performance, architecture, SSR, optimisation |
| Expert | 31–40 | ~25h | Micro-frontends, WASM, monorepo, design system |
| Total | 40 | ~70h | Programme complet |