Cours Next.js · Module 1: Configuration de Next.js
Introduction à React et Next.js - histoire, avantages, écosystème
Dans cette leçon7
Bienvenue à Quantum Metropolis, le centre technologique de l'an 2150, où les bâtiments touchent le ciel, les véhicules flottent dans les airs et un réseau quantique omniprésent connecte tous les aspects de la vie quotidienne. Ici, la technologie fait partie intégrante de la société, tout comme React et Next.js sont des composants fondamentaux de l'écosystème web moderne.
La naissance de la technologie React
Dans l'histoire du développement des technologies web, React a été comme le premier moteur antigravité fonctionnel - il a révolutionné la façon dont nous construisons les interfaces utilisateur. Créé en 2011 par un ingénieur de Facebook (aujourd'hui Meta) et publié en open source en 2013, React a introduit un concept révolutionnaire : des composants déclaratifs avec un DOM virtuel.
React a résolu l'un des problèmes les plus importants du développement d'applications web - la complexité de la mise à jour de l'interface utilisateur. Au lieu de manipuler directement le DOM (ce qui était coûteux et source d'erreurs), React permettait aux développeurs de raisonner en termes d'état et de composants :
1// Simple composant React
2function WelcomePanel() {
3 const [userName, setUserName] = React.useState("Citizen");
4
5 return (
6 <div className="quantum-panel">
7 <h2>Welcome, {userName}!</h2>
8 <p>Quantum Metropolis Terminal at your service.</p>
9 <button onClick={() => setUserName("Administrator")}>
10 Log in
11 </button>
12 </div>
13 );
14}Le composant ci-dessus est comme un panneau de contrôle intelligent de Quantum Metropolis - il réagit automatiquement aux changements d'état (ici userName), sans avoir besoin de contrôler manuellement chaque élément de l'interface.
Le code React plus ancien utilise aussi des composants de classe (class Panel extends React.Component). Ils fonctionnent toujours, mais les nouveaux composants s'écrivent sous forme de fonctions.
L'évolution vers Next.js
Malgré ses avantages, React n'était qu'une bibliothèque d'interface utilisateur. Les développeurs devaient toujours configurer eux-mêmes le routage, l'optimisation des performances, le rendu côté serveur et bien d'autres aspects.
Next.js est apparu en 2016 comme un framework construit au-dessus de React, fournissant des solutions toutes prêtes à ces problèmes. On peut comparer cela au passage du prototype de moteur antigravité à un véhicule volant pleinement fonctionnel à Quantum Metropolis.
Fonctionnalités clés de Next.js :
Rendu hybride - la possibilité de faire du rendu côté serveur (SSR), du rendu statique (SSG) et du rendu côté client
Routage basé sur le système de fichiers - création des chemins de l'application à partir de la structure des dossiers
Découpage automatique du code - division du code en plus petites parties, chargées uniquement lorsque c'est nécessaire
Optimisation des images - traitement et diffusion automatiques des images dans des formats optimaux
Zéro configuration - fonctionne immédiatement après l'installation, avec une configuration minimale
API Routes - création de points d'accès API dans le même projet que le frontend
Next.js 16 et l'App Router
Dans Next.js 16, le routeur recommandé est l'App Router - un changement révolutionnaire apparu dans Next.js 13, qui apporte une toute nouvelle approche de l'organisation des applications (l'ancien Pages Router fonctionne toujours). C'est comme passer des véhicules volants traditionnels à la téléportation quantique à Quantum Metropolis - un changement de paradigme fondamental.
L'App Router exploite les dernières fonctionnalités de React 19.2, notamment les React Server Components, qui changent le modèle traditionnel des applications web. Au lieu de traiter toute l'application comme une unité rendue côté client, l'App Router permet de mélanger de manière flexible des composants rendus côté serveur et côté client.
1// app/dashboard/page.tsx - Server Component
2export default async function DashboardPage() {
3 // This code runs ONLY on the server
4 const dashboardData = await fetchDashboardData();
5
6 return (
7 <main className="quantum-dashboard">
8 <h1>Quantum Metropolis Control Panel</h1>
9 <StatusPanel data={dashboardData.status} />
10 <InteractiveControls /> {/* This will be a client component */}
11 </main>
12 );
13}1// app/dashboard/interactive-controls.tsx - Client Component
2"use client"; // This directive marks a client component
3
4import { useState } from 'react';
5
6export default function InteractiveControls() {
7 // This code runs in the user's browser
8 const [activeSystem, setActiveSystem] = useState('energy');
9
10 return (
11 <div className="control-panel">
12 <h2>System: {activeSystem}</h2>
13 <button onClick={() => setActiveSystem('transport')}>
14 Transport
15 </button>
16 <button onClick={() => setActiveSystem('energy')}>
17 Energy
18 </button>
19 <button onClick={() => setActiveSystem('security')}>
20 Security
21 </button>
22 </div>
23 );
24}L'écosystème React et Next.js
L'écosystème React et Next.js est comme l'infrastructure avancée de Quantum Metropolis - vaste, intégré et en constante évolution. Voici les éléments clés de cet écosystème :
Bibliothèques de gestion de l'état :
- Redux - solution complète pour les applications complexes
- Zustand - alternative plus légère et plus simple
- Jotai - architecture d'état atomique
- React Query / SWR - gestion de l'état serveur
Bibliothèques de style :
- Tailwind CSS - système de classes utilitaires
- Styled Components / Emotion - CSS-in-JS
- CSS Modules - intégré à Next.js
- Chakra UI / MUI - composants UI tout prêts
Tests :
- Jest - framework de tests
- React Testing Library - tests de composants
- Cypress / Playwright - tests end-to-end
Outils pour les développeurs :
- ESLint - analyse statique du code
- Prettier - formatage du code
- TypeScript - typage statique
- Next.js DevTools - outils de développement Next.js
Avantages de l'utilisation de React et Next.js
Utiliser React et Next.js dans des projets web apporte des bénéfices similaires à ceux dont profitent les habitants de Quantum Metropolis grâce à l'infrastructure avancée de la ville :
Performance - optimisations comme le code splitting, le prefetching, l'optimisation des images
Évolutivité - l'architecture par composants facilite la gestion des grandes applications
Expérience développeur - boucle de feedback rapide grâce au hot reloading, structure de projet claire
SEO - le rendu côté serveur et la génération statique améliorent l'indexation par les moteurs de recherche
Écosystème - riche sélection de bibliothèques et d'outils
Communauté - une communauté immense et active, et une documentation abondante
Structure d'un projet Next.js avec App Router
Dans l'App Router, la structure du projet ressemble aux cartes des quartiers et aux systèmes de transport de Quantum Metropolis - tout a sa place et sa fonction :
1app/ # Main application directory
2├── layout.tsx # Main application layout
3├── page.tsx # Home page
4├── globals.css # Global styles
5├── dashboard/ # Route /dashboard
6│ ├── layout.tsx # Layout for the entire dashboard section
7│ ├── page.tsx # Page /dashboard
8│ └── analytics/ # Route /dashboard/analytics
9│ └── page.tsx # Page /dashboard/analytics
10├── auth/ # Route /auth
11│ ├── login/ # Route /auth/login
12│ │ └── page.tsx # Page /auth/login
13│ └── register/ # Route /auth/register
14│ └── page.tsx # Page /auth/register
15└── api/ # API Routes
16 └── status/ # Endpoint /api/status
17 └── route.ts # API handler for /api/statusDans cette structure, la navigation est intuitive et les composants partagés sont automatiquement réutilisés sur les différentes pages. C'est un énorme avantage par rapport aux applications React traditionnelles, où la gestion du routage pouvait être compliquée.
Résumé
React et Next.js forment un duo puissant dans le développement d'applications web modernes, tout comme le réseau quantique et l'infrastructure avancée forment le cœur du fonctionnement de Quantum Metropolis.
React fournit le modèle de composants et la gestion d'état qui rendent la construction des interfaces utilisateur plus prévisible et plus facile à maintenir. Next.js ajoute la structure, les optimisations et les outils qui transforment React en une plateforme complète pour construire des applications web.
À mesure que nous avancerons dans les prochains modules, tu apprendras les applications pratiques de ces technologies, tout comme en explorant Quantum Metropolis tu découvriras tous ses systèmes avancés.
Code de cette leçon : App.tsx
1// React et Next.js - Metropolis Quantum
2import React, { useState, useEffect } from 'react';
3import './App.css';
4
5console.log("Bienvenue à Metropolis Quantum !");
6console.log("Apprentissage de React et Next.js - l'avenir du développement web\n");
7
8// ===========================================
9// 1. Composants React - fondamentaux
10// ===========================================
11console.log("=== 1. COMPOSANTS REACT ===");
12
13// Composant React fonctionnel
14const QuantumButton: React.FC<{
15 children: React.ReactNode;
16 onClick: () => void;
17 variant?: 'primary' | 'secondary' | 'quantum';
18}> = ({ children, onClick, variant = 'primary' }) => {
19 const [isActivated, setIsActivated] = useState(false);
20
21 const handleClick = () => {
22 setIsActivated(true);
23 onClick();
24 setTimeout(() => setIsActivated(false), 300);
25 };
26
27 return (
28 <button
29 className={`quantum-btn quantum-btn--${variant} ${isActivated ? 'activated' : ''}`}
30 onClick={handleClick}
31 >
32 {children}
33 {isActivated && <span className="quantum-ripple"></span>}
34 </button>
35 );
36};
37
38// Composant avec le Hook useState
39const QuantumCounter: React.FC = () => {
40 const [energy, setEnergy] = useState(0);
41 const [isCharging, setIsCharging] = useState(false);
42
43 const generateEnergy = () => {
44 setIsCharging(true);
45
46 const interval = setInterval(() => {
47 setEnergy(prev => {
48 const newEnergy = prev + Math.floor(Math.random() * 10) + 1;
49 if (newEnergy >= 100) {
50 clearInterval(interval);
51 setIsCharging(false);
52 console.log("Batterie quantique entièrement chargée !");
53 return 100;
54 }
55 return newEnergy;
56 });
57 }, 200);
58 };
59
60 const resetEnergy = () => {
61 setEnergy(0);
62 setIsCharging(false);
63 console.log("Batterie quantique réinitialisée");
64 };
65
66 return (
67 <div className="quantum-counter">
68 <h3>Générateur d'énergie quantique</h3>
69 <div className="energy-display">
70 <div className="energy-bar">
71 <div
72 className="energy-fill"
73 style={{ width: `${energy}%` }}
74 ></div>
75 </div>
76 <span className="energy-text">{energy}% Énergie</span>
77 </div>
78
79 <div className="counter-controls">
80 <QuantumButton
81 onClick={generateEnergy}
82 variant="quantum"
83 disabled={isCharging}
84 >
85 {isCharging ? 'Chargement...' : 'Générer de l\'énergie'}
86 </QuantumButton>
87
88 <QuantumButton
89 onClick={resetEnergy}
90 variant="secondary"
91 >
92 Réinitialiser
93 </QuantumButton>
94 </div>
95
96 {energy === 100 && (
97 <div className="achievement">
98 Succès débloqué : Maître Quantique !
99 </div>
100 )}
101 </div>
102 );
103};
104
105// ===========================================
106// 2. Hook useEffect - effets de bord
107// ===========================================
108console.log("=== 2. HOOK USE EFFECT ===");
109
110const QuantumClock: React.FC = () => {
111 const [currentTime, setCurrentTime] = useState(new Date());
112 const [quantumTime, setQuantumTime] = useState(0);
113
114 // useEffect pour les mises à jour de l'heure
115 useEffect(() => {
116 console.log("Horloge quantique activée");
117
118 const timer = setInterval(() => {
119 setCurrentTime(new Date());
120 setQuantumTime(prev => prev + 1);
121 }, 1000);
122
123 // Fonction de nettoyage
124 return () => {
125 clearInterval(timer);
126 console.log("Horloge quantique désactivée");
127 };
128 }, []); // Tableau de dépendances vide - exécuté une seule fois
129
130 // useEffect avec dépendance
131 useEffect(() => {
132 if (quantumTime > 0 && quantumTime % 10 === 0) {
133 console.log(`Point de contrôle du temps quantique : ${quantumTime} secondes`);
134 }
135 }, [quantumTime]); // Exécuté quand quantumTime change
136
137 const formatTime = (date: Date) => {
138 return date.toLocaleTimeString('fr-FR');
139 };
140
141 return (
142 <div className="quantum-clock">
143 <h3>Portail temporel quantique</h3>
144 <div className="time-display">
145 <div className="real-time">
146 <span className="time-label">Heure terrestre :</span>
147 <span className="time-value">{formatTime(currentTime)}</span>
148 </div>
149 <div className="quantum-time">
150 <span className="time-label">Heure quantique :</span>
151 <span className="time-value">{quantumTime}s</span>
152 </div>
153 </div>
154 </div>
155 );
156};
157
158// ===========================================
159// 3. React vs DOM traditionnel
160// ===========================================
161console.log("=== 3. REACT VS DOM TRADITIONNEL ===");
162
163const DOMComparison: React.FC = () => {
164 const [items, setItems] = useState<string[]>(['Quantum Core', 'Energy Shield', 'Plasma Drive']);
165 const [newItem, setNewItem] = useState('');
166
167 // Méthode React - déclarative
168 const addItemReact = () => {
169 if (newItem.trim()) {
170 setItems(prev => [...prev, newItem.trim()]);
171 setNewItem('');
172 console.log(`Méthode React : "${newItem}" ajouté à l'inventaire quantique`);
173 }
174 };
175
176 // Méthode DOM traditionnelle (pour comparaison)
177 const addItemTraditional = () => {
178 console.log("Méthode DOM traditionnelle (non recommandée dans React) :");
179 console.log(" 1. document.getElementById('list')");
180 console.log(" 2. createElement('li')");
181 console.log(" 3. appendChild(listItem)");
182 console.log(" 4. Gestion manuelle des écouteurs d'événements");
183 console.log(" 5. Synchronisation manuelle de l'état");
184 };
185
186 return (
187 <div className="dom-comparison">
188 <h3>React vs DOM traditionnel</h3>
189
190 <div className="react-way">
191 <h4>Méthode React (déclarative)</h4>
192 <div className="input-group">
193 <input
194 type="text"
195 value={newItem}
196 onChange={(e) => setNewItem(e.target.value)}
197 placeholder="Saisis un composant quantique..."
198 className="quantum-input"
199 />
200 <QuantumButton onClick={addItemReact}>
201 Ajouter à l'inventaire
202 </QuantumButton>
203 </div>
204
205 <div className="inventory-list">
206 <h5>Inventaire quantique :</h5>
207 <ul>
208 {items.map((item, index) => (
209 <li key={index} className="inventory-item">
210 {item}
211 <button
212 onClick={() => setItems(prev => prev.filter((_, i) => i !== index))}
213 className="remove-btn"
214 >
215 ×
216 </button>
217 </li>
218 ))}
219 </ul>
220 </div>
221 </div>
222
223 <div className="traditional-way">
224 <h4>Méthode DOM traditionnelle</h4>
225 <QuantumButton onClick={addItemTraditional} variant="secondary">
226 Montrer l'approche traditionnelle
227 </QuantumButton>
228 <p className="comparison-note">
229 React gère automatiquement les mises à jour du DOM grâce au Virtual DOM !
230 </p>
231 </div>
232 </div>
233 );
234};
235
236// ===========================================
237// 4. Composition de composants
238// ===========================================
239console.log("=== 4. COMPOSITION DE COMPOSANTS ===");
240
241interface QuantumModuleProps {
242 title: string;
243 status: 'online' | 'offline' | 'maintenance';
244 children: React.ReactNode;
245}
246
247const QuantumModule: React.FC<QuantumModuleProps> = ({ title, status, children }) => {
248 const getStatusColor = () => {
249 switch (status) {
250 case 'online': return '#4caf50';
251 case 'offline': return '#f44336';
252 case 'maintenance': return '#ff9800';
253 default: return '#999';
254 }
255 };
256
257 return (
258 <div className="quantum-module">
259 <div className="module-header">
260 <h4>{title}</h4>
261 <div
262 className={`status-indicator status-${status}`}
263 style={{ backgroundColor: getStatusColor() }}
264 >
265 {status.toUpperCase()}
266 </div>
267 </div>
268 <div className="module-content">
269 {children}
270 </div>
271 </div>
272 );
273};
274
275const MetropolisControlPanel: React.FC = () => {
276 const [systemStatus, setSystemStatus] = useState<'online' | 'offline' | 'maintenance'>('online');
277
278 const toggleSystem = () => {
279 setSystemStatus(prev => {
280 const statuses: Array<'online' | 'offline' | 'maintenance'> = ['online', 'maintenance', 'offline'];
281 const currentIndex = statuses.indexOf(prev);
282 const nextStatus = statuses[(currentIndex + 1) % statuses.length];
283 console.log(`Statut du système modifié : ${prev} → ${nextStatus}`);
284 return nextStatus;
285 });
286 };
287
288 return (
289 <div className="control-panel">
290 <h3>Panneau de contrôle de la Metropolis</h3>
291
292 <QuantumModule title="Système de propulsion" status={systemStatus}>
293 <p>Les moteurs à propulsion quantique fonctionnent à leur efficacité optimale</p>
294 <div className="metric">
295 <span>Vitesse : </span>
296 <span className="value">
297 {systemStatus === 'online' ? '299,792,458 m/s' : 'OFFLINE'}
298 </span>
299 </div>
300 </QuantumModule>
301
302 <QuantumModule title="Grille défensive" status={systemStatus}>
303 <p>Boucliers énergétiques protégeant la métropole</p>
304 <div className="metric">
305 <span>Puissance du bouclier : </span>
306 <span className="value">
307 {systemStatus === 'online' ? '98.7%' : 'OFFLINE'}
308 </span>
309 </div>
310 </QuantumModule>
311
312 <QuantumModule title="Hub de communication" status={systemStatus}>
313 <p>Réseau de communication par intrication quantique</p>
314 <div className="metric">
315 <span>Force du signal : </span>
316 <span className="value">
317 {systemStatus === 'online' ? 'Excellent' : 'OFFLINE'}
318 </span>
319 </div>
320 </QuantumModule>
321
322 <div className="panel-controls">
323 <QuantumButton onClick={toggleSystem} variant="quantum">
324 Changer le statut du système
325 </QuantumButton>
326 </div>
327 </div>
328 );
329};
330
331// ===========================================
332// 5. Aperçu de Next.js
333// ===========================================
334console.log("=== 5. APERÇU DE NEXT.JS ===");
335
336const NextJSPreview: React.FC = () => {
337 const [currentFeature, setCurrentFeature] = useState(0);
338
339 const nextjsFeatures = [
340 {
341 title: "App Router",
342 description: "Système de routage basé sur les fichiers avec layouts et routage imbriqué",
343 code: `app/
344├── layout.tsx // Root layout
345├── page.tsx // Home page
346├── dashboard/
347│ ├── layout.tsx // Dashboard layout
348│ └── page.tsx // Dashboard page
349└── api/
350 └── route.ts // API endpoint`
351 },
352 {
353 title: "Server Components",
354 description: "Rendu des composants sur le serveur pour de meilleures performances",
355 code: `// app/quantum/page.tsx
356async function QuantumPage() {
357 // This runs on the server!
358 const data = await fetch('https://api.quantum.com/data');
359 const quantumData = await data.json();
360
361 return <div>{quantumData.energy}</div>;
362}`
363 },
364 {
365 title: "Stratégies de rendu",
366 description: "SSR, SSG, ISR - choisis la meilleure stratégie pour ton application",
367 code: `// Static Site Generation
368export async function generateStaticParams() {
369 return [{ id: '1' }, { id: '2' }];
370}
371
372// Server Side Rendering
373async function DynamicPage() {
374 const data = await fetch(url, { cache: 'no-store' });
375 return <div>{data}</div>;
376}`
377 },
378 {
379 title: "Optimisations intégrées",
380 description: "Code splitting automatique, optimisation des images, optimisation des polices",
381 code: `import Image from 'next/image';
382import { Inter } from 'next/font/google';
383
384const inter = Inter({ subsets: ['latin'] });
385
386export default function Page() {
387 return (
388 <div className={inter.className}>
389 <Image
390 src="/quantum.jpg"
391 alt="Quantum City"
392 width={800}
393 height={600}
394 priority
395 />
396 </div>
397 );
398}`
399 }
400 ];
401
402 const nextFeature = () => {
403 setCurrentFeature(prev => (prev + 1) % nextjsFeatures.length);
404 };
405
406 const prevFeature = () => {
407 setCurrentFeature(prev => (prev - 1 + nextjsFeatures.length) % nextjsFeatures.length);
408 };
409
410 const feature = nextjsFeatures[currentFeature];
411
412 return (
413 <div className="nextjs-preview">
414 <h3>Fonctionnalités de Next.js 16</h3>
415
416 <div className="feature-showcase">
417 <div className="feature-header">
418 <h4>{feature.title}</h4>
419 <p>{feature.description}</p>
420 </div>
421
422 <div className="feature-code">
423 <pre><code>{feature.code}</code></pre>
424 </div>
425
426 <div className="feature-navigation">
427 <QuantumButton onClick={prevFeature} variant="secondary">
428 Précédent
429 </QuantumButton>
430
431 <span className="feature-counter">
432 {currentFeature + 1} / {nextjsFeatures.length}
433 </span>
434
435 <QuantumButton onClick={nextFeature} variant="secondary">
436 Suivant
437 </QuantumButton>
438 </div>
439 </div>
440 </div>
441 );
442};
443
444// ===========================================
445// 6. Composant App principal
446// ===========================================
447const App: React.FC = () => {
448 const [activeSection, setActiveSection] = useState('intro');
449
450 useEffect(() => {
451 console.log("Application Metropolis Quantum initialisée");
452 console.log("Prêt à explorer React et Next.js !");
453 }, []);
454
455 const sections = {
456 intro: { title: "Introduction", component: () => (
457 <div className="intro-section">
458 <h2>Bienvenue à Metropolis Quantum !</h2>
459 <p>
460 Dans la ville futuriste de Metropolis Quantum, où la technologie rencontre la magie,
461 nous apprenons les fondamentaux de React et Next.js - des outils qui permettent de construire
462 des applications web interactives de nouvelle génération.
463 </p>
464 <div className="intro-features">
465 <div className="feature-card">
466 <h4>React</h4>
467 <p>Bibliothèque pour construire des interfaces utilisateur</p>
468 </div>
469 <div className="feature-card">
470 <h4>Next.js</h4>
471 <p>Framework React avec des capacités supplémentaires</p>
472 </div>
473 <div className="feature-card">
474 <h4>TypeScript</h4>
475 <p>Typage statique pour une plus grande sécurité</p>
476 </div>
477 </div>
478 </div>
479 )},
480 components: { title: "Composants", component: () => <QuantumCounter /> },
481 hooks: { title: "Hooks", component: () => <QuantumClock /> },
482 comparison: { title: "Comparaison DOM", component: () => <DOMComparison /> },
483 composition: { title: "Composition", component: () => <MetropolisControlPanel /> },
484 nextjs: { title: "Next.js", component: () => <NextJSPreview /> }
485 };
486
487 return (
488 <div className="metropolis-app">
489 <header className="app-header">
490 <h1>Metropolis Quantum</h1>
491 <p>Plateforme d'apprentissage React & Next.js</p>
492 </header>
493
494 <nav className="app-navigation">
495 {Object.entries(sections).map(([key, section]) => (
496 <QuantumButton
497 key={key}
498 onClick={() => setActiveSection(key)}
499 variant={activeSection === key ? 'quantum' : 'secondary'}
500 >
501 {section.title}
502 </QuantumButton>
503 ))}
504 </nav>
505
506 <main className="app-content">
507 <div className="content-container">
508 {sections[activeSection as keyof typeof sections].component()}
509 </div>
510 </main>
511
512 <footer className="app-footer">
513 <p>Propulsé par la technologie quantique • Apprends React & Next.js</p>
514 </footer>
515 </div>
516 );
517};
518
519export default App;Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. En quelle année React a-t-il été publié en open source ?
2. React a été créé par :
3. Le principal avantage de React est :
Tâches pratiques dans le jeu
- Éditeur de code
Crée un composant fonctionnel nommé HelloWorld qui retourne un titre <h1> avec un message de bienvenue, par exemple « Bienvenue à Metropolis Quantum ! ».
- Clique dans l'ordre
Ordonne la déclaration d'un composant fonctionnel en React