---
source_hash: "5cf6f77b"
title: "Chapter 4: ES6 Modules"
weight: 340
---

# Chapter 4: ES6 Modules

## Introduction

ES6 modules allow you to organize code into separate files, with an explicit import/export system.

In PHP, you use `require`, `include`, or PSR-4 autoloading. In modern JavaScript, we use `import` and `export`.

## Export

### Named Export

Allows exporting multiple elements from a file:

```javascript
// utils/math.js

// Export at declaration
export const PI = 3.14159;

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

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

// OR grouped export at the end
const PI = 3.14159;
function add(a, b) { return a + b; }
const multiply = (a, b) => a * b;

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

### Default Export

Only one default export per file. Generally used for the main component/class:

```javascript
// components/Button.jsx

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

export default Button;

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

### Mixing Both

```javascript
// services/api.js

// Default export: main API client
const apiClient = {
    get: (url) => fetch(url).then(r => r.json()),
    post: (url, data) => fetch(url, { method: 'POST', body: JSON.stringify(data) })
};

// Named exports: utilities
export const API_URL = "https://api.example.com";
export const handleError = (error) => console.error(error);

export default apiClient;
```

## Import

### Named Import

```javascript
// Import named exports (braces required)
import { add, multiply } from './utils/math.js';
import { PI } from './utils/math.js';

// Rename on import
import { add as addition } from './utils/math.js';

// Import everything under a namespace
import * as MathUtils from './utils/math.js';
// Usage: MathUtils.add(1, 2), MathUtils.PI
```

### Default Import

```javascript
// Import default export (no braces)
import Button from './components/Button.jsx';

// The name is free (not linked to the name in the source file)
import MonBouton from './components/Button.jsx'; // OK
```

### Mixed Import

```javascript
// Default + named in the same import
import apiClient, { API_URL, handleError } from './services/api.js';
```

## Import Paths

### Relative Paths

```javascript
// Same directory
import { helper } from './helper.js';

// Parent directory
import { config } from '../config.js';

// Subdirectory
import Button from './components/Button.jsx';
```

### Package Imports (node_modules)

```javascript
// npm packages - no relative path
import React from 'react';
import { useState, useEffect } from 'react';
import axios from 'axios';
```

### Path Aliases (Vite/Webpack)

SmartMaker configures a `src` alias:

```javascript
// Without alias (fragile relative paths)
import Button from '../../../components/Button.jsx';

// With alias (cleaner)
import Button from 'src/components/Button.jsx';
```

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

## Comparison with PHP

```php
// PHP - PSR-4 autoloading
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` | No direct equivalent (file = module) |
| `use App\Class` | `import Class from 'path'` |
| `new Class()` | `new Class()` or component `<Class />` |
| Autoloading | Bundler (Vite/Webpack) resolves imports |

## React File Organization

### Typical SmartMaker Structure

```
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

When a directory contains `index.jsx`, you can import the directory directly:

```javascript
// These two imports are equivalent
import Button from './components/common/Button/index.jsx';
import Button from './components/common/Button';
```

### Barrel File (re-export)

A file that re-exports multiple modules:

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

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

## Dynamic Import

For code-splitting (lazy loading):

```javascript
// Static import (loaded at startup)
import HeavyComponent from './HeavyComponent';

// Dynamic import (loaded when needed)
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));

// Usage with Suspense
<Suspense fallback={<Loading />}>
    <HeavyComponent />
</Suspense>
```

## Exercises

### Exercise 1: Create a Module

Create a file `utils/string.js` that exports:

- A constant `DEFAULT_LOCALE = "fr-FR"`
- A function `capitalize(str)` that capitalizes the first letter
- A default function `formatName(firstName, lastName)` that returns "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)}`;
}
```

### Exercise 2: Import the Module

Import and use the created module:

```javascript
// app.js
// 1. Import formatName (default)
// 2. Import capitalize and DEFAULT_LOCALE (named)
// 3. Display formatName("jean", "dupont")
// 4. Display 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"
```

## Key Points to Remember

1. **Named export**: `export const x` or `export { x, y }`
2. **Default export**: `export default X` (only one per file)
3. **Named import**: `import { x, y } from './file'` (braces)
4. **Default import**: `import X from './file'` (no braces)
5. **Alias**: `import { x as alias } from './file'`
6. **Import all**: `import * as Module from './file'`
7. **index.jsx**: allows `import X from './folder'`

## Module 1 Summary

You now have the ES6+ JavaScript basics needed for React:

| Concept | Syntax |
| --- | --- |
| Variables | `const`, `let` |
| Destructuring | `const { a, b } = obj` |
| Spread | `{ ...obj }`, `[...arr]` |
| Arrow functions | `(x) => x * 2` |
| Default parameters | `(x = 10) => ...` |
| Template literals | `` `Hello ${name}` `` |
| Promises | `.then()`, `.catch()` |
| async/await | `async function`, `await` |
| Modules | `import`, `export` |

[<- Previous Chapter](/training/module1-javascript-es6/asynchrone) | [Back to Module](/training/module1-javascript-es6) | [Next Module: Introduction to React ->](/training/module2-introduction-react)
