---
title: "Chapitre 4 : Modules ES6"
weight: 340
---

# Chapitre 4 : Modules ES6

## Introduction

Les modules ES6 permettent d'organiser le code en fichiers séparés, avec un système d'import/export explicite.

En PHP, vous utilisez `require`, `include`, ou l'autoloading PSR-4. En JavaScript moderne, on utilise `import` et `export`.

## Export

### Export nommé (Named Export)

Permet d'exporter plusieurs éléments depuis un fichier :

```javascript
// utils/math.js

// Export à la déclaration
export const PI = 3.14159;

export function add(a, b) {
    return a + b;
}

export const multiply = (a, b) => a * b;

// OU export groupé à la fin
const PI = 3.14159;
function add(a, b) { return a + b; }
const multiply = (a, b) => a * b;

export { PI, add, multiply };
```

### Export par défaut (Default Export)

Un seul export par défaut par fichier. Généralement utilisé pour le composant/classe principal :

```javascript
// components/Button.jsx

const Button = ({ label, onClick }) => {
    return <button onClick={onClick}>{label}</button>;
};

export default Button;

// OU directement
export default function Button({ label, onClick }) {
    return <button onClick={onClick}>{label}</button>;
}
```

### Mélange des deux

```javascript
// services/api.js

// Export par défaut : le client API principal
const apiClient = {
    get: (url) => fetch(url).then(r => r.json()),
    post: (url, data) => fetch(url, { method: 'POST', body: JSON.stringify(data) })
};

// Exports nommés : utilitaires
export const API_URL = "https://api.example.com";
export const handleError = (error) => console.error(error);

export default apiClient;
```

## Import

### Import nommé

```javascript
// Importer des exports nommés (accolades obligatoires)
import { add, multiply } from './utils/math.js';
import { PI } from './utils/math.js';

// Renommer à l'import
import { add as addition } from './utils/math.js';

// Importer tout sous un namespace
import * as MathUtils from './utils/math.js';
// Utilisation : MathUtils.add(1, 2), MathUtils.PI
```

### Import par défaut

```javascript
// Importer l'export par défaut (pas d'accolades)
import Button from './components/Button.jsx';

// Le nom est libre (pas lié au nom dans le fichier source)
import MonBouton from './components/Button.jsx'; // OK
```

### Import mixte

```javascript
// Default + named dans le même import
import apiClient, { API_URL, handleError } from './services/api.js';
```

## Chemins d'import

### Chemins relatifs

```javascript
// Même dossier
import { helper } from './helper.js';

// Dossier parent
import { config } from '../config.js';

// Sous-dossier
import Button from './components/Button.jsx';
```

### Imports de packages (node_modules)

```javascript
// Packages npm - pas de chemin relatif
import React from 'react';
import { useState, useEffect } from 'react';
import axios from 'axios';
```

### Alias de chemins (Vite/Webpack)

SmartMaker configure un alias `src` :

```javascript
// Sans alias (chemins relatifs fragiles)
import Button from '../../../components/Button.jsx';

// Avec alias (plus propre)
import Button from 'src/components/Button.jsx';
```

Configuration dans `vite.config.js` :
```javascript
export default defineConfig({
    resolve: {
        alias: {
            'src': '/src'
        }
    }
});
```

## Comparaison avec PHP

```php
// PHP - autoloading PSR-4
namespace App\Services;

use App\Models\User;
use App\Utils\Helper;

class UserService {
    // ...
}
```

```javascript
// JavaScript ES6
import User from 'src/models/User.js';
import { formatDate } from 'src/utils/helper.js';

export default class UserService {
    // ...
}
```

| PHP | JavaScript |
| --- | --- |
| `namespace` | Pas d'équivalent direct (le fichier = le module) |
| `use App\Class` | `import Class from 'path'` |
| `new Class()` | `new Class()` ou composant `<Class />` |
| Autoloading | Bundler (Vite/Webpack) résout les imports |

## Organisation des fichiers React

### Structure typique SmartMaker

```
src/
├── components/
│   ├── app/                    # Providers, Router
│   │   ├── SmartCommonProvider/
│   │   │   └── index.jsx       # export default SmartCommonProvider
│   │   └── Router/
│   │       └── index.jsx
│   │
│   ├── pages/
│   │   ├── public/
│   │   │   └── LoginPage/
│   │   │       └── index.jsx
│   │   └── private/
│   │       └── HomePage/
│   │           └── index.jsx
│   │
│   └── common/
│       ├── Button/
│       │   └── index.jsx
│       └── Card/
│           └── index.jsx
│
├── hooks/
│   └── useAuth.js
│
├── services/
│   └── api.js
│
└── utils/
    └── format.js
```

### Convention : index.jsx

Quand un dossier contient `index.jsx`, on peut importer le dossier directement :

```javascript
// Ces deux imports sont équivalents
import Button from './components/common/Button/index.jsx';
import Button from './components/common/Button';
```

### Fichier barrel (re-export)

Un fichier qui re-exporte plusieurs modules :

```javascript
// components/common/index.js
export { default as Button } from './Button';
export { default as Card } from './Card';
export { default as Modal } from './Modal';

// Utilisation
import { Button, Card, Modal } from 'src/components/common';
```

## Import dynamique

Pour le code-splitting (chargement à la demande) :

```javascript
// Import statique (chargé au démarrage)
import HeavyComponent from './HeavyComponent';

// Import dynamique (chargé quand nécessaire)
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));

// Utilisation avec Suspense
<Suspense fallback={<Loading />}>
    <HeavyComponent />
</Suspense>
```

## Exercices

### Exercice 1 : Créer un module

Créer un fichier `utils/string.js` qui exporte :

- Une constante `DEFAULT_LOCALE = "fr-FR"`
- Une fonction `capitalize(str)` qui met la première lettre en majuscule
- Une fonction par défaut `formatName(firstName, lastName)` qui retourne "LASTNAME Firstname"

**Solution :**

```javascript
// utils/string.js

export const DEFAULT_LOCALE = "fr-FR";

export function capitalize(str) {
    if (!str) return '';
    return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
}

export default function formatName(firstName, lastName) {
    return `${lastName.toUpperCase()} ${capitalize(firstName)}`;
}
```

### Exercice 2 : Importer le module

Importer et utiliser le module créé :

```javascript
// app.js
// 1. Importer formatName (default)
// 2. Importer capitalize et DEFAULT_LOCALE (named)
// 3. Afficher formatName("jean", "dupont")
// 4. Afficher capitalize("bonjour")
```

**Solution :**

```javascript
// app.js
import formatName, { capitalize, DEFAULT_LOCALE } from './utils/string.js';

console.log(formatName("jean", "dupont")); // "DUPONT Jean"
console.log(capitalize("bonjour"));         // "Bonjour"
console.log(DEFAULT_LOCALE);                // "fr-FR"
```

## Points clés à retenir

1. **Export nommé** : `export const x` ou `export { x, y }`
2. **Export default** : `export default X` (un seul par fichier)
3. **Import nommé** : `import { x, y } from './file'` (accolades)
4. **Import default** : `import X from './file'` (pas d'accolades)
5. **Alias** : `import { x as alias } from './file'`
6. **Tout importer** : `import * as Module from './file'`
7. **index.jsx** : permet `import X from './folder'`

## Récapitulatif du Module 1

Vous avez maintenant les bases JavaScript ES6+ nécessaires pour React :

| Concept | Syntaxe |
| --- | --- |
| Variables | `const`, `let` |
| Déstructuration | `const { a, b } = obj` |
| Spread | `{ ...obj }`, `[...arr]` |
| Arrow functions | `(x) => x * 2` |
| Paramètres défaut | `(x = 10) => ...` |
| Template literals | `` `Hello ${name}` `` |
| Promises | `.then()`, `.catch()` |
| async/await | `async function`, `await` |
| Modules | `import`, `export` |

[← Chapitre précédent](/training/module1-javascript-es6/asynchrone) | [Retour au module](/training/module1-javascript-es6) | [Module suivant : Introduction à React ->](/training/module2-introduction-react)
