Cours Next.js · Module 1: Configuration de Next.js
Environnement de développement - outils et pratiques
Dans cette leçon4
À Quantum Metropolis, les ingénieurs quantiques ont besoin de postes de travail avancés, d'outils précis et de processus optimisés pour concevoir et maintenir efficacement les systèmes avancés de la ville. De même, en tant que développeur Next.js 16, ton environnement de développement est le fondement de ta productivité et de la qualité de ton code.
Le centre de commande de Quantum Metropolis
Commençons par configurer l'environnement de développement idéal - ton Centre de commande personnel pour les projets Next.js 16.
Outils de base
1. Éditeur de code - le terminal quantique
Le cœur du poste de travail de chaque ingénieur quantique est le Terminal quantique. Pour les développeurs Next.js 16, Visual Studio Code (VS Code) avec des extensions est le meilleur choix :
1# Install basic extensions
2code --install-extension dbaeumer.vscode-eslint
3code --install-extension esbenp.prettier-vscode
4code --install-extension bradlc.vscode-tailwindcss
5code --install-extension ms-vscode.vscode-typescript-next
6code --install-extension dsznajder.es7-react-js-snippetsConfiguration de VSCode pour les projets Next.js 16 - fichier .vscode/settings.json :
1{
2 "editor.formatOnSave": true,
3 "editor.defaultFormatter": "esbenp.prettier-vscode",
4 "editor.codeActionsOnSave": {
5 "source.fixAll.eslint": true
6 },
7 "typescript.tsdk": "node_modules/typescript/lib",
8 "typescript.enablePromptUseWorkspaceTsdk": true,
9 "tailwindCSS.includeLanguages": {
10 "typescript": "javascript",
11 "typescriptreact": "javascript"
12 },
13 "tailwindCSS.experimental.classRegex": [
14 ["cn\\(([^)]*)\\)", "'([^']*)'"]
15 ],
16 "files.associations": {
17 "*.css": "tailwindcss"
18 }
19}2. Système de contrôle de version - les archives quantiques
À Quantum Metropolis, chaque changement des systèmes de la ville est soigneusement enregistré et stocké dans les Archives quantiques. Dans notre monde, nous utilisons Git :
1# Initialize a Git repository for the project
2git init
3
4# Create a .gitignore file for Next.js projects
5curl -fsSL https://raw.githubusercontent.com/github/gitignore/main/Nextjs.gitignore -o .gitignoreLe fichier .gitignore pour un projet Next.js 16 :
1# dependencies
2/node_modules
3/.pnp
4.pnp.*
5.yarn/*
6!.yarn/patches
7!.yarn/plugins
8!.yarn/releases
9!.yarn/versions
10
11# testing
12/coverage
13
14# next.js
15/.next/
16/out/
17
18# production
19/build
20
21# misc
22.DS_Store
23*.pem
24
25# debug
26npm-debug.log*
27yarn-debug.log*
28yarn-error.log*
29.pnpm-debug.log*
30
31# env files (can opt-in for committing if needed)
32.env*
33
34# vercel
35.vercel
36
37# typescript
38*.tsbuildinfo
39next-env.d.tsVoici le .gitignore que génère create-next-app dans Next.js 16. Remarque la ligne .env* : depuis Next.js 15, tous les fichiers d'environnement sont ignorés, pas seulement .env*.local, pour que les secrets ne se retrouvent pas par accident dans le dépôt. Si tu veux y enregistrer un fichier de valeurs d'exemple, ajoute une exception comme !.env.example.
3. Gestion des paquets - la matrice de ressources quantiques
Les ingénieurs de Quantum Metropolis utilisent la Matrice de ressources quantiques pour obtenir exactement les composants dont ils ont besoin. Nous utilisons npm, yarn ou pnpm :
1# Initialize a Next.js 16 project with Tailwind CSS and TypeScript
2npx create-next-app@latest quantum-project
3# Choose "Yes, use recommended defaults": TypeScript, ESLint,
4# Tailwind CSS, App Router and AGENTS.md in one stepEn option, tu peux configurer pnpm pour de meilleures performances :
1# Install pnpm
2npm install -g pnpm
3
4# Initialize project with pnpm
5pnpm dlx create-next-app@latest quantum-projectOutils de productivité
1. ESLint - le détecteur d'anomalies quantiques
À Quantum Metropolis, des scanners avancés surveillent en permanence le code à la recherche de bugs potentiels et de patterns sous-optimaux. Dans le monde de Next.js 16, ESLint remplit cette fonction :
1npm install --save-dev eslint-plugin-jsx-a11yLe paquet eslint-config-next contient déjà les règles recommandées des plugins react et react-hooks et enregistre le plugin jsx-a11y avec quelques règles d'accessibilité : nous installons donc seulement eslint-plugin-jsx-a11y pour activer son ensemble recommandé complet. Configuration d'ESLint dans eslint.config.mjs :
1// eslint.config.mjs
2import { defineConfig, globalIgnores } from 'eslint/config';
3import nextVitals from 'eslint-config-next/core-web-vitals';
4import nextTs from 'eslint-config-next/typescript';
5import jsxA11y from 'eslint-plugin-jsx-a11y';
6
7const eslintConfig = defineConfig([
8 ...nextVitals,
9 ...nextTs,
10 {
11 rules: {
12 ...jsxA11y.flatConfigs.recommended.rules,
13 'react/react-in-jsx-scope': 'off',
14 'react/prop-types': 'off',
15 '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
16 'jsx-a11y/anchor-is-valid': ['error', {
17 components: ['Link'],
18 specialLink: ['hrefLeft', 'hrefRight'],
19 aspects: ['invalidHref', 'preferButton'],
20 }],
21 },
22 },
23 globalIgnores(['.next/**', 'out/**', 'build/**', 'next-env.d.ts']),
24]);
25
26export default eslintConfig;Les règles écrites après l'ensemble recommended déplié écrasent ses réglages, c'est pourquoi anchor-is-valid comprend le composant Link de Next.js. Le réglage de la version de React (settings.react.version) n'est plus nécessaire, car eslint-config-next la détecte automatiquement.
2. Prettier - l'harmoniseur de code quantique
Tout comme à Quantum Metropolis toutes les structures doivent être parfaitement harmonisées, ton code doit être formaté de manière cohérente :
1npm install --save-dev prettier eslint-config-prettierConfiguration de Prettier dans .prettierrc :
1{
2 "semi": true,
3 "singleQuote": true,
4 "tabWidth": 2,
5 "printWidth": 100,
6 "trailingComma": "es5",
7 "bracketSpacing": true,
8 "arrowParens": "avoid"
9}Et ajoute la configuration eslint-config-prettier à la fin du tableau dans eslint.config.mjs pour désactiver les règles ESLint qui entrent en conflit avec le formatage :
1// eslint.config.mjs (fragment)
2import prettier from 'eslint-config-prettier/flat';
3
4const eslintConfig = defineConfig([
5 ...nextVitals,
6 ...nextTs,
7 // ...rest of the configuration
8 prettier,
9 globalIgnores(['.next/**', 'out/**', 'build/**', 'next-env.d.ts']),
10]);3. Husky et lint-staged - les gardiens quantiques automatiques
À Quantum Metropolis, avant qu'un code ne soit introduit dans les systèmes de la ville, il passe par une série de tests et de validations automatiques. De même, nous pouvons configurer Husky et lint-staged :
1npm install --save-dev husky lint-staged
2npx husky init
3echo "npx lint-staged" > .husky/pre-commitConfiguration de lint-staged dans package.json :
1{
2 "lint-staged": {
3 "*.{js,jsx,ts,tsx}": [
4 "eslint --fix",
5 "prettier --write"
6 ],
7 "*.{json,css,md}": [
8 "prettier --write"
9 ]
10 }
11}4. TypeScript - le système de types quantique
À Quantum Metropolis, tous les composants doivent suivre strictement leurs spécifications pour garantir la sécurité de l'ensemble du système. TypeScript apporte une sécurité similaire à ton code :
1# TypeScript is already installed in a Next.js 16 project
2# Let's configure stricter TypeScript rulesConfiguration de tsconfig.json :
1{
2 "compilerOptions": {
3 "target": "ES2017",
4 "lib": ["dom", "dom.iterable", "esnext"],
5 "allowJs": true,
6 "skipLibCheck": true,
7 "strict": true,
8 "noUncheckedIndexedAccess": true,
9 "forceConsistentCasingInFileNames": true,
10 "noEmit": true,
11 "esModuleInterop": true,
12 "module": "esnext",
13 "moduleResolution": "bundler",
14 "resolveJsonModule": true,
15 "isolatedModules": true,
16 "jsx": "react-jsx",
17 "incremental": true,
18 "plugins": [
19 {
20 "name": "next"
21 }
22 ],
23 "paths": {
24 "@/*": ["./src/*"]
25 }
26 },
27 "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts", "**/*.mts"],
28 "exclude": ["node_modules"]
29}Voici le tsconfig.json d'un projet Next.js 16, complété par l'option noUncheckedIndexedAccess (noImplicitAny et strictNullChecks sont déjà activées par "strict": true). create-next-app définit "jsx": "react-jsx" et "moduleResolution": "bundler", et ajoute le répertoire .next/dev/types à include, car next dev écrit désormais ses fichiers séparément dans .next/dev.
Outils de test - simulations quantiques
Les ingénieurs de Quantum Metropolis lancent des milliers de simulations avant chaque changement pour s'assurer que les systèmes de la ville fonctionneront sans faille. L'équivalent dans le monde de Next.js 16 sont les outils de test :
1. Jest et React Testing Library - simulations de base
1npm install --save-dev jest @testing-library/react @testing-library/jest-dom jest-environment-jsdomFichier de configuration jest.config.js :
1const nextJest = require('next/jest');
2
3const createJestConfig = nextJest({
4 // Folder where next.config.js and node_modules are located
5 dir: './',
6});
7
8// Jest configuration
9const customJestConfig = {
10 setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
11 testEnvironment: 'jest-environment-jsdom',
12 moduleNameMapper: {
13 '^@/(.*)$': '<rootDir>/src/$1',
14 },
15};
16
17// Export the configuration
18module.exports = createJestConfig(customJestConfig);Fichier de setup jest.setup.js :
1// Jest extensions
2import '@testing-library/jest-dom';Scripts de test dans package.json :
1{
2 "scripts": {
3 "test": "jest",
4 "test:watch": "jest --watch"
5 }
6}2. Cypress - simulations avancées
1npm install --save-dev cypressInitialiser Cypress :
1npx cypress openAjoute des scripts à package.json :
1{
2 "scripts": {
3 "cypress": "cypress open",
4 "cypress:headless": "cypress run"
5 }
6}3. Storybook - la bibliothèque de composants quantiques
1npm create storybook@latestL'assistant te demande s'il faut utiliser la version basée sur Vite ou sur Webpack. Configure Storybook pour Next.js 16 dans .storybook/main.ts :
1// .storybook/main.ts
2import type { StorybookConfig } from '@storybook/nextjs-vite';
3
4const config: StorybookConfig = {
5 stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
6 addons: ['@storybook/addon-docs'],
7 framework: '@storybook/nextjs-vite',
8 staticDirs: ['../public'],
9};
10
11export default config;Le framework @storybook/nextjs-vite connaît les spécificités de Next.js, comme next/image, next/font et le routage, c'est pourquoi la documentation de Storybook le recommande pour la plupart des projets Next.js. Choisis la version basée sur Webpack (@storybook/nextjs) seulement si tu as besoin d'une configuration Webpack ou Babel personnalisée.
Pratiques de développement optimisées
À Quantum Metropolis, chaque ingénieur suit des normes et des procédures strictement définies. Examinons les meilleures pratiques pour les développeurs Next.js 16.
1. Structure du projet - le plan de la Metropolis
Tout comme Quantum Metropolis est divisée en secteurs précisément conçus, ton projet Next.js 16 devrait avoir une structure claire :
1quantum-voyages/
2 ├── .husky/ # Husky configuration
3 ├── .vscode/ # VS Code configuration
4 ├── public/ # Static assets
5 ├── src/
6 │ ├── app/ # App Router - routes and pages
7 │ │ ├── (auth)/ # Logical grouping for authorization
8 │ │ │ ├── login/
9 │ │ │ └── register/
10 │ │ ├── destinations/ # Route for destinations
11 │ │ ├── bookings/ # Route for bookings
12 │ │ ├── api/ # API endpoints
13 │ │ └── layout.tsx # Main layout
14 │ ├── components/ # React components
15 │ │ ├── ui/ # UI elements
16 │ │ └── features/ # Feature-specific components
17 │ ├── hooks/ # Custom React hooks
18 │ ├── lib/ # Utility functions and business logic
19 │ ├── styles/ # Global styles and themes
20 │ ├── types/ # TypeScript type definitions
21 │ └── utils/ # Utility functions
22 ├── tests/ # Integration and end-to-end tests
23 │ ├── e2e/ # Cypress tests
24 │ └── integration/ # Integration tests
25 ├── .env.example # Example environment variables file
26 ├── .gitignore # Git ignored files
27 ├── .prettierrc # Prettier configuration
28 ├── eslint.config.mjs # ESLint configuration (flat config)
29 ├── jest.config.js # Jest configuration
30 ├── next.config.ts # Next.js configuration
31 ├── package.json # Dependencies and scripts
32 ├── postcss.config.mjs # PostCSS configuration (for Tailwind CSS 4)
33 └── tsconfig.json # TypeScript configuration2. Conventions de nommage - protocoles quantiques
À Quantum Metropolis, chaque élément porte un nom précis qui reflète sa fonction. De même dans le code :
1// Components: PascalCase, .tsx files
2// components/ui/QuantumButton.tsx
3export default function QuantumButton() {
4 return <button className="bg-blue-500 text-white px-4 py-2 rounded">Quantum</button>;
5}
6
7// Utility functions: camelCase, .ts files
8// utils/formatDate.ts
9export function formatDate(date: Date): string {
10 return new Intl.DateTimeFormat('en-US').format(date);
11}
12
13// Hooks: name starts with 'use', camelCase, .ts files
14// hooks/useQuantumState.ts
15export function useQuantumState(initialValue: number) {
16 const [state, setState] = useState(initialValue);
17 //
18 return { state, increment, decrement };
19}
20
21// Contexts: name ends with 'Context', PascalCase
22// contexts/QuantumContext.tsx
23export const QuantumContext = createContext<QuantumContextType | null>(null);3. Workflows Git - protocoles de contrôle de version de la Metropolis
À Quantum Metropolis, chaque changement des systèmes de la ville doit passer par un processus précis d'approbation et de déploiement. Dans le monde de la programmation, il vaut la peine de suivre Gitflow :
1# Creating a new feature
2git checkout -b feature/quantum-navigation
3
4# Commits with descriptive messages
5git commit -m "feat: Add quantum navigation component"
6git commit -m "fix: Repair positioning in quantum nav"
7git commit -m "docs: Add JSdoc comments to navigation functions"
8
9# Completing the feature and merging to develop
10git checkout develop
11git merge feature/quantum-navigationStandards des messages de commit (Conventional Commits) :
- feat : nouvelle fonctionnalité
- fix : correction de bug
- docs : changements de documentation
- style : formatage du code
- refactor : refactorisation du code
- test : ajout ou mise à jour de tests
- chore : mises à jour des tâches de build, des outils, etc.
4. Approche par composants - concevoir des modules quantiques
Atomic Design
À Quantum Metropolis, tous les systèmes sont construits à partir de particules quantiques de base qui se combinent en structures de plus en plus complexes. Un modèle similaire - l'Atomic Design - peut être appliqué à la conception d'interfaces :
- Atoms (atomes) - composants de base : boutons, inputs, labels
- Molecules (molécules) - groupes d'atomes : formulaires de recherche, navigation
- Organisms (organismes) - sections d'interface complexes : en-têtes, pieds de page, barres latérales
- Templates (gabarits) - layouts de page
- Pages - instances spécifiques de gabarits avec des données
1components/
2 ├── atoms/
3 │ ├── Button.tsx
4 │ ├── Input.tsx
5 │ └── Label.tsx
6 ├── molecules/
7 │ ├── SearchForm.tsx
8 │ └── NavLink.tsx
9 ├── organisms/
10 │ ├── Header.tsx
11 │ └── Footer.tsx
12 └── templates/
13 ├── DashboardLayout.tsx
14 └── AuthLayout.tsxComposants basés sur le pattern « Composition et API »
Tout comme à Quantum Metropolis chaque module a son interface et peut être combiné avec d'autres modules, nos composants doivent être conçus de manière modulaire :
1// Example component with composition pattern
2import { ReactNode } from 'react';
3
4interface CardProps {
5 className?: string;
6 children: ReactNode;
7}
8
9export function Card({ className, children }: CardProps) {
10 return <div className={`rounded-lg shadow ${className}`}>{children}</div>;
11}
12
13Card.Header = function CardHeader({ className, children }: CardProps) {
14 return <div className={`p-4 border-b ${className}`}>{children}</div>;
15};
16
17Card.Body = function CardBody({ className, children }: CardProps) {
18 return <div className={`p-4 ${className}`}>{children}</div>;
19};
20
21Card.Footer = function CardFooter({ className, children }: CardProps) {
22 return <div className={`p-4 border-t ${className}`}>{children}</div>;
23};
24
25// Usage
26<Card className="bg-white">
27 <Card.Header>Quantum Navigation</Card.Header>
28 <Card.Body>Card content</Card.Body>
29 <Card.Footer>Actions</Card.Footer>
30</Card>5. Automatisation des tâches - systèmes automatiques quantiques
À Quantum Metropolis, de nombreux processus sont automatisés pour que les ingénieurs puissent se concentrer sur l'innovation. De même dans un projet Next.js 16 :
1// package.json
2{
3 "scripts": {
4 "dev": "next dev",
5 "build": "next build",
6 "start": "next start",
7 "lint": "eslint",
8 "format": "prettier --write .",
9 "test": "jest",
10 "test:watch": "jest --watch",
11 "e2e": "cypress open",
12 "storybook": "storybook dev -p 6006",
13 "build-storybook": "storybook build",
14 "prepare": "husky",
15 "type-check": "tsc --noEmit",
16 "validate": "npm-run-all --parallel lint type-check test"
17 }
18}Le script validate lance plusieurs commandes à la fois avec l'outil npm-run-all, qu'il faut installer : npm install --save-dev npm-run-all2 (le paquet npm-run-all2 fournit la commande npm-run-all).
6. Gestion de l'état - gestion des données quantiques
À Quantum Metropolis, les données circulent dans la ville via un système quantique complexe. Dans une application Next.js 16, nous avons aussi besoin d'une gestion efficace de l'état :
Gestion de l'état local
1// Using useState and useReducer for simple state management
2"use client";
3
4import { useState } from 'react';
5
6export default function QuantumCounter() {
7 const [count, setCount] = useState(0);
8
9 return (
10 <div className="flex items-center gap-4">
11 <button
12 onClick={() => setCount(c => c - 1)}
13 className="px-3 py-1 bg-red-500 text-white rounded"
14 >
15 -
16 </button>
17 <span className="text-xl">{count}</span>
18 <button
19 onClick={() => setCount(c => c + 1)}
20 className="px-3 py-1 bg-green-500 text-white rounded"
21 >
22 +
23 </button>
24 </div>
25 );
26}Gestion de l'état au niveau de l'application
1// Context API - for medium-sized applications
2// contexts/QuantumStateContext.tsx
3"use client";
4
5import { createContext, useContext, useReducer, ReactNode } from 'react';
6
7type State = {
8 destinations: string[];
9 selectedDestination: string | null;
10};
11
12type Action =
13 | { type: 'ADD_DESTINATION'; payload: string }
14 | { type: 'SELECT_DESTINATION'; payload: string };
15
16const initialState: State = {
17 destinations: ['Mars', 'Europa', 'Titan'],
18 selectedDestination: null,
19};
20
21function reducer(state: State, action: Action): State {
22 switch (action.type) {
23 case 'ADD_DESTINATION':
24 return {
25 ...state,
26 destinations: [...state.destinations, action.payload],
27 };
28 case 'SELECT_DESTINATION':
29 return {
30 ...state,
31 selectedDestination: action.payload,
32 };
33 default:
34 return state;
35 }
36}
37
38const QuantumStateContext = createContext<{
39 state: State;
40 dispatch: React.Dispatch<Action>;
41} | undefined>(undefined);
42
43export function QuantumStateProvider({ children }: { children: ReactNode }) {
44 const [state, dispatch] = useReducer(reducer, initialState);
45
46 return (
47 <QuantumStateContext.Provider value={{ state, dispatch }}>
48 {children}
49 </QuantumStateContext.Provider>
50 );
51}
52
53export function useQuantumState() {
54 const context = useContext(QuantumStateContext);
55 if (context === undefined) {
56 throw new Error('useQuantumState must be used within a QuantumStateProvider');
57 }
58 return context;
59}Pour les applications plus importantes, envisage des bibliothèques de gestion d'état comme Zustand, Jotai ou Redux Toolkit.
7. Stratégie d'API - protocoles de communication quantiques
À Quantum Metropolis, les systèmes communiquent à l'aide de protocoles précis. Dans Next.js 16, nous avons plusieurs options pour implémenter des API :
Route Handlers
1// app/api/destinations/route.ts
2import { NextResponse } from 'next/server';
3
4export async function GET() {
5 // Fetching data from a database or external API
6 const destinations = [
7 { id: 1, name: 'Mars', distance: '54.6M km' },
8 { id: 2, name: 'Europa', distance: '628.3M km' },
9 { id: 3, name: 'Titan', distance: '1.2B km' },
10 ];
11
12 return NextResponse.json(destinations);
13}
14
15export async function POST(request: Request) {
16 const body = await request.json();
17
18 // Validation and business logic
19 if (!body.name) {
20 return NextResponse.json(
21 { error: 'Name is required' },
22 { status: 400 }
23 );
24 }
25
26 // Saving to database...
27
28 return NextResponse.json(
29 { id: 4, name: body.name, distance: body.distance },
30 { status: 201 }
31 );
32}Server Actions
1// app/destinations/actions.ts
2'use server';
3
4import { revalidatePath } from 'next/cache';
5import { redirect } from 'next/navigation';
6
7export async function addDestination(formData: FormData) {
8 const name = formData.get('name') as string;
9 const distance = formData.get('distance') as string;
10
11 if (!name || !distance) {
12 return { error: 'Name and distance are required' };
13 }
14
15 // Saving to database...
16
17 // Refresh data
18 revalidatePath('/destinations');
19 redirect('/destinations');
20}React Query pour la gestion de l'état des API
1npm install @tanstack/react-query @tanstack/react-query-devtools1// app/providers.tsx
2'use client';
3
4import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
5import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
6import { useState, ReactNode } from 'react';
7
8export function Providers({ children }: { children: ReactNode }) {
9 const [queryClient] = useState(() => new QueryClient());
10
11 return (
12 <QueryClientProvider client={queryClient}>
13 {children}
14 <ReactQueryDevtools initialIsOpen={false} />
15 </QueryClientProvider>
16 );
17}1// components/DestinationsList.tsx
2'use client';
3
4import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
5
6async function fetchDestinations() {
7 const res = await fetch('/api/destinations');
8 if (!res.ok) throw new Error('Failed to fetch destinations');
9 return res.json();
10}
11
12export default function DestinationsList() {
13 const queryClient = useQueryClient();
14
15 const { data: destinations, isLoading, error } = useQuery({
16 queryKey: ['destinations'],
17 queryFn: fetchDestinations,
18 });
19
20 const mutation = useMutation({
21 mutationFn: async (newDestination) => {
22 const res = await fetch('/api/destinations', {
23 method: 'POST',
24 headers: { 'Content-Type': 'application/json' },
25 body: JSON.stringify(newDestination),
26 });
27 return res.json();
28 },
29 onSuccess: () => {
30 queryClient.invalidateQueries({ queryKey: ['destinations'] });
31 },
32 });
33
34 if (isLoading) return <div>Loading destinations...</div>;
35 if (error) return <div>Error: {error.message}</div>;
36
37 return (
38 <div>
39 <h2 className="text-2xl font-bold mb-4">Available destinations</h2>
40 <ul className="space-y-2">
41 {destinations.map((dest) => (
42 <li key={dest.id} className="p-3 bg-gray-100 rounded">
43 {dest.name} - {dest.distance}
44 </li>
45 ))}
46 </ul>
47 </div>
48 );
49}8. Intégration et déploiement continus (CI/CD) - le pipeline de production quantique
À Quantum Metropolis, les nouvelles technologies sont systématiquement testées et déployées via un processus entièrement automatisé. De même, nous pouvons configurer une CI/CD pour notre projet :
GitHub Actions pour la CI/CD
Fichier .github/workflows/ci.yml :
1name: CI
2
3on:
4 push:
5 branches: [ main, develop ]
6 pull_request:
7 branches: [ main, develop ]
8
9jobs:
10 build:
11 runs-on: ubuntu-latest
12
13 steps:
14 - uses: actions/checkout@v7
15
16 - name: Setup Node.js
17 uses: actions/setup-node@v7
18 with:
19 node-version: '24'
20 cache: 'npm'
21
22 - name: Install dependencies
23 run: npm ci
24
25 - name: Lint
26 run: npm run lint
27
28 - name: Type check
29 run: npm run type-check
30
31 - name: Test
32 run: npm test
33
34 - name: Build
35 run: npm run buildDéploiement sur Vercel
Configure l'intégration Vercel pour que chaque push sur la branche main déploie automatiquement l'application :
- Connecte ton dépôt à Vercel
- Configure les variables d'environnement
- Utilise les Preview Deployments pour les pull requests
- Déploiement automatique en production après le merge avec la branche main
Techniques de développement avancées
1. Surveillance des performances - télémétrie quantique
À Quantum Metropolis, les ingénieurs surveillent en permanence les performances de tous les systèmes. Dans notre application Next.js 16 :
1// app/layout.tsx
2import { SpeedInsights } from '@vercel/speed-insights/next';
3import { Analytics } from '@vercel/analytics/react';
4
5export default function RootLayout({
6 children,
7}: {
8 children: React.ReactNode;
9}) {
10 return (
11 <html lang="en">
12 <body>
13 {children}
14 <SpeedInsights />
15 <Analytics />
16 </body>
17 </html>
18 );
19}2. Améliorations progressives et accessibilité - adaptation quantique universelle
À Quantum Metropolis, chaque citoyen doit avoir accès aux systèmes de la ville, quelles que soient ses limitations. De même, notre application doit être accessible à tous :
1// components/ui/QuantumButton.tsx with enhanced accessibility
2"use client";
3
4import { ButtonHTMLAttributes, forwardRef } from 'react';
5
6interface QuantumButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
7 variant?: 'primary' | 'secondary' | 'danger';
8 size?: 'sm' | 'md' | 'lg';
9 isLoading?: boolean;
10}
11
12export const QuantumButton = forwardRef<HTMLButtonElement, QuantumButtonProps>(
13 ({
14 variant = 'primary',
15 size = 'md',
16 className = '',
17 isLoading = false,
18 disabled,
19 children,
20 ...props
21 }, ref) => {
22 // Map variants to classes
23 const variantClasses = {
24 primary: 'bg-blue-600 hover:bg-blue-700 text-white',
25 secondary: 'bg-gray-200 hover:bg-gray-300 text-gray-800',
26 danger: 'bg-red-600 hover:bg-red-700 text-white',
27 };
28
29 // Map sizes to classes
30 const sizeClasses = {
31 sm: 'text-sm px-2 py-1',
32 md: 'text-base px-4 py-2',
33 lg: 'text-lg px-6 py-3',
34 };
35
36 return (
37 <button
38 ref={ref}
39 className={`rounded font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 ${variantClasses[variant]} ${sizeClasses[size]} ${isLoading || disabled ? 'opacity-70 cursor-not-allowed' : ''} ${className}`}
40 disabled={isLoading || disabled}
41 {...props}
42 >
43 {isLoading ? (
44 <span className="flex items-center justify-center">
45 <svg className="animate-spin -ml-1 mr-2 h-4 w-4 text-current" fill="none" viewBox="0 0 24 24">
46 <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
47 <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
48 </svg>
49 Loading...
50 </span>
51 ) : children}
52 </button>
53 );
54 }
55);
56QuantumButton.displayName = 'QuantumButton';3. Documentation du code - l'archiviste quantique
À Quantum Metropolis, chaque système est minutieusement documenté afin que les futurs ingénieurs puissent le comprendre facilement. Dans notre projet :
1/**
2 * Navigation component for space travel.
3 *
4 * @component
5 * @example
6 * ~~~tsx
7 * <QuantumNavigation
8 * destinations={['Mars', 'Europa', 'Titan']}
9 * onSelectDestination={(dest) => console.log(`Selected ${dest}`)}
10 * />
11 * ~~~
12 */
13export interface QuantumNavigationProps {
14 /** List of available destinations */
15 destinations: string[];
16 /** Callback invoked when a destination is selected */
17 onSelectDestination: (destination: string) => void;
18 /** Currently selected destination (optional) */
19 selectedDestination?: string;
20}
21
22export function QuantumNavigation({
23 destinations,
24 onSelectDestination,
25 selectedDestination
26}: QuantumNavigationProps) {
27 return (
28 <nav className="p-4 bg-gradient-to-r from-indigo-500 to-purple-600 rounded-lg text-white">
29 <h2 className="text-xl font-semibold mb-2">Quantum Navigation</h2>
30 <ul className="space-y-1">
31 {destinations.map((dest) => (
32 <li key={dest}>
33 <button
34 className={`w-full text-left px-3 py-2 rounded hover:bg-white/20 ${
35 selectedDestination === dest ? 'bg-white/30 font-medium' : ''
36 }`}
37 onClick={() => onSelectDestination(dest)}
38 >
39 {dest}
40 </button>
41 </li>
42 ))}
43 </ul>
44 </nav>
45 );
46}4. Collaboration en équipe - le collectif quantique
À Quantum Metropolis, les ingénieurs travaillent en équipes synchronisées pour atteindre une efficacité maximale. De même, une équipe de développement Next.js 16 devrait avoir des processus de collaboration clairs :
- Code Reviews - chaque pull request devrait être relue par au moins un autre développeur
- Pair Programming - résoudre les problèmes plus difficiles à deux
- Standups - courtes réunions quotidiennes pour synchroniser le travail
- Sprint Planning - planification des tâches du prochain sprint
- Rétrospectives - réunions régulières pour discuter de ce qui fonctionne et de ce qui peut être amélioré
Résumé
Tout comme les ingénieurs de Quantum Metropolis ont besoin d'outils avancés et de processus optimaux, les développeurs Next.js 16 ont besoin d'un environnement de développement bien configuré. Avec les outils et les pratiques présentés, tu peux :
- Augmenter la productivité - automatisation des tâches répétitives
- Améliorer la qualité du code - linting, tests, typage
- Faciliter la collaboration - conventions cohérentes, CI/CD, structure claire
- Accélérer le développement - retour rapide, débogage efficace
- Garantir une haute qualité - tests automatisés, code reviews
Souviens-toi que, tout comme Quantum Metropolis évolue en permanence, ton environnement de développement devrait évoluer avec le projet et l'équipe. Révise et mets régulièrement à jour tes outils et processus pour maintenir une efficacité et une qualité de code maximales.
Toutes les connaissances et tous les outils présentés dans ce module te permettront de créer efficacement des applications avancées avec Next.js 16 - tout comme les ingénieurs quantiques de la Metropolis utilisent leurs outils pour concevoir les technologies de demain.
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. Quel outil est responsable du formatage automatique du code à l'enregistrement du fichier ?
2. À quoi servent Husky et lint-staged dans un projet ?
3. Quel gestionnaire de paquets économise de l'espace disque grâce à un dépôt de paquets partagé et adressé par contenu ?
Tâches pratiques dans le jeu
- Tri vertical
Ordonne les étapes de travail sur une fonctionnalité dans le workflow Gitflow