Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Использование модулей в Frontend
Да, модули — это основа современной JavaScript разработки. Я использую их постоянно и считаю правильную организацию модулей критичной для качества кода.
Что такое модули?
Модуль — это самодостаточный файл с кодом, который экспортирует функциональность и может импортировать то, что ему нужно. Это позволяет разбить большое приложение на маленькие, управляемые куски.
ESM (ES Modules) — современный стандарт
// utils/math.js
export function add(a, b) {
return a + b;
}
export const PI = 3.14159;
// components/Button.jsx
import { add, PI } from '../utils/math.js';
export function Button() {
const result = add(2, 3);
return <button>Result: {result}</button>;
}
Типы экспортов
Named export
// utils.js
export function greet(name) {
return `Hello, ${name}`;
}
export const APP_NAME = 'MyApp';
// app.js
import { greet, APP_NAME } from './utils.js';
console.log(greet('Alice')); // Hello, Alice
Default export
// Button.jsx
export default function Button() {
return <button>Click me</button>;
}
// app.jsx
import Button from './Button.jsx';
// Можешь назвать как угодно
Комбинированно
// Button.jsx
export default function Button() {
return <button>Click</button>;
}
export const BUTTON_STYLES = { /* ... */ };
// app.jsx
import Button, { BUTTON_STYLES } from './Button.jsx';
Структура модулей в приложении
В большом приложении модули организуют по слоям:
src/
domain/ # Бизнес логика (независима от framework)
user/
types.ts # User, UserProfile интерфейсы
validators.ts
application/ # Use cases, бизнес правила
user/
getUserById.ts
updateUser.ts
infrastructure/ # API клиент, БД, внешние сервисы
api/
client.ts
endpoints.ts
presentation/ # UI компоненты
components/
Button.jsx
UserCard.jsx
pages/
HomePage.jsx
hooks/
useUser.ts
Практические примеры
1. Разделение логики и UI
// hooks/useUser.ts
export function useUser(userId) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetchUser(userId)
.then(setUser)
.catch(setError)
.finally(() => setLoading(false));
}, [userId]);
return { user, loading, error };
}
// components/UserProfile.jsx
import { useUser } from '../hooks/useUser';
export function UserProfile({ userId }) {
const { user, loading, error } = useUser(userId);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>{user.name}</div>;
}
2. Утилиты и константы
// utils/formatters.ts
export function formatDate(date) {
return date.toLocaleDateString('en-US');
}
export function formatCurrency(amount) {
return `$${amount.toFixed(2)}`;
}
// constants.ts
export const API_BASE_URL = process.env.REACT_APP_API_URL;
export const PAGINATION_SIZE = 20;
export const CACHE_TTL = 5 * 60 * 1000; // 5 минут
// components/PriceTag.jsx
import { formatCurrency } from '../utils/formatters';
import { CACHE_TTL } from '../constants';
export function PriceTag({ price }) {
return <span>{formatCurrency(price)}</span>;
}
3. Custom хуки как модули
// hooks/useLocalStorage.ts
export function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
});
const setValue = (value) => {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
};
return [storedValue, setValue];
}
// components/ThemeSelector.jsx
import { useLocalStorage } from '../hooks/useLocalStorage';
export function ThemeSelector() {
const [theme, setTheme] = useLocalStorage('theme', 'light');
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Current theme: {theme}
</button>
);
}
4. API клиент как модуль
// lib/api.ts
class ApiClient {
constructor(baseURL, token) {
this.baseURL = baseURL;
this.token = token;
}
async request(endpoint, options = {}) {
const url = `${this.baseURL}${endpoint}`;
const headers = {
'Content-Type': 'application/json',
...(this.token && { 'Authorization': `Bearer ${this.token}` }),
...options.headers
};
const response = await fetch(url, { ...options, headers });
if (!response.ok) {
throw new Error(`API Error: ${response.status}`);
}
return response.json();
}
get(endpoint) {
return this.request(endpoint);
}
post(endpoint, data) {
return this.request(endpoint, {
method: 'POST',
body: JSON.stringify(data)
});
}
}
export const api = new ApiClient(
process.env.REACT_APP_API_URL,
localStorage.getItem('token')
);
// components/UserList.jsx
import { api } from '../lib/api';
export function UserList() {
const [users, setUsers] = useState([]);
useEffect(() => {
api.get('/users').then(setUsers);
}, []);
return (
<ul>
{users.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}
Лучшие практики с модулями
1. Одна ответственность на модуль
// ПЛОХО: всё в одном файле
// Button.jsx содержит Button, IconButton, LoadingButton...
// ХОРОШО: разные модули
// Button.jsx — только Button
// IconButton.jsx — только IconButton
// LoadingButton.jsx — только LoadingButton
2. Явные экспорты
// ПЛОХО: экспортируем всё подряд
export * from './utils';
// ХОРОШО: явно выбираем что экспортировать
export { formatDate, formatCurrency } from './utils';
3. Правильная структура импортов
// ПОРЯДОК ИМПОРТОВ:
// 1. Внешние библиотеки
import React from 'react';
import { useEffect, useState } from 'react';
// 2. Внутренние модули (абсолютные пути)
import { api } from '@/lib/api';
import { useUser } from '@/hooks/useUser';
// 3. Локальные модули (относительные пути)
import { UserCard } from './UserCard';
import styles from './UserList.module.css';
// ПУСТО
// Код компонента
export function UserList() { /* ... */ }
4. Избегай циклических зависимостей
// ПЛОХО: A импортирует B, B импортирует A
// userService.js
import { logger } from './logger';
// logger.js
import { userService } from './userService'; // Циклическая зависимость!
// ХОРОШО: используй разные модули
// domain/user.ts (типы)
// application/userService.ts
// infrastructure/logger.ts
5. Барьелы (index.ts)
// components/index.ts
export { Button } from './Button';
export { Card } from './Card';
export { Modal } from './Modal';
// app.jsx
// ВМЕСТО:
import { Button } from './components/Button';
import { Card } from './components/Card';
import { Modal } from './components/Modal';
// ПИШЕШЬ:
import { Button, Card, Modal } from './components';
Модули и производительность
Tree-shaking
Сборщик удаляет неиспользуемые экспорты:
// utils.js
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }
// app.js
import { add } from './utils'; // Используем только add
// Сборщик удалит subtract из финального бандла
Code splitting
Делишь большое приложение на отдельные модули, которые загружаются по требованию:
import { lazy, Suspense } from 'react';
const AdminPanel = lazy(() => import('./pages/AdminPanel'));
export function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<AdminPanel />
</Suspense>
);
}
Итог
Модули — это стандарт современного JavaScript. Они позволяют:
- Организовать код в понятную структуру
- Избежать конфликтов имён (каждый модуль имеет своё пространство)
- Переиспользовать код (импортируй модуль везде)
- Тестировать каждый модуль отдельно
- Оптимизировать приложение (tree-shaking, code splitting)
Правильное использование модулей — это основа чистого, поддерживаемого кода.