Cours Next.js · Module 1: Configuration de Next.js

Introduction à React et Next.js - histoire, avantages, écosystème

7 min de lecture
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 :

  1. Rendu hybride - la possibilité de faire du rendu côté serveur (SSR), du rendu statique (SSG) et du rendu côté client

  2. Routage basé sur le système de fichiers - création des chemins de l'application à partir de la structure des dossiers

  3. Découpage automatique du code - division du code en plus petites parties, chargées uniquement lorsque c'est nécessaire

  4. Optimisation des images - traitement et diffusion automatiques des images dans des formats optimaux

  5. Zéro configuration - fonctionne immédiatement après l'installation, avec une configuration minimale

  6. 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 :

  1. Performance - optimisations comme le code splitting, le prefetching, l'optimisation des images

  2. Évolutivité - l'architecture par composants facilite la gestion des grandes applications

  3. Expérience développeur - boucle de feedback rapide grâce au hot reloading, structure de projet claire

  4. SEO - le rendu côté serveur et la génération statique améliorent l'indexation par les moteurs de recherche

  5. Écosystème - riche sélection de bibliothèques et d'outils

  6. 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/status

Dans 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. 1. En quelle année React a-t-il été publié en open source ?

  2. 2. React a été créé par :

  3. 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

Articles utiles