EvolCode
треки/С нуля·09 / 11
5 мин чтения

Модули — import и export

Когда ИИ генерирует код для проекта, он почти всегда раскидан по нескольким файлам, и сверху каждого — `import ... from ...`. Это и есть модули. Без понимания этой системы любой проект больше одного файла будет загадкой.

Зачем разбивать на файлы

Один файл с тысячами строк нечитаем, медленно открывается, и в нём легко словить конфликты при работе командой. Разбиваем по смыслу: компоненты в одной папке, утилиты в другой, типы в третьей. Каждый файл = модуль. Модули общаются через export (что отдаёт) и import (что забирает).

Named export vs default export

Named:

$ export function foo() {}

экспортируем под именем foo. Импорт строго по имени: import { foo } from "./file". Можно много таких в одном файле. Default:

$ export default function foo() {}

основной экспорт файла, имя при импорте можно ЛЮБОЕ: import foo from "./file" или import bar from "./file". По одному default на файл.

Пути — относительные и пакеты

Относительный путь начинается с ./ или ../: ./utils.js (тот же каталог), ../shared/format.js (на уровень выше). Без точки — это пакет из node_modules: import React from "react". В Next.js часто видишь @/components/... — это alias на корневую папку src/, настраивается в tsconfig.json.

Re-export — собирающий файл

Часто видишь index.ts который ничего не делает кроме

$ export { Foo } from "./Foo"; export { Bar } from "./Bar";

Это «бочка» (barrel) — собирает экспорты подпапки, чтобы импортировать одним путём:

$ import { Foo, Bar } from "./components"

вместо двух разных путей.

примерtypescript
// === src/lib/format.ts — утилиты ===
export function formatPrice(n: number) {
  return n.toLocaleString('ru-RU') + ' ₽';
}

export function formatDate(d: Date) {
  return d.toLocaleDateString('ru-RU');
}

// Default export — один на файл
export default function noop() {}

// === src/lib/api.ts — клиент API ===
export async function fetchUser(id: string) { /* ... */ }
export async function fetchProduct(id: string) { /* ... */ }

// === src/lib/index.ts — barrel-файл ===
export { formatPrice, formatDate } from './format';
export { fetchUser, fetchProduct } from './api';

// === src/components/PriceTag.tsx ===
import { formatPrice } from '@/lib';                // alias из tsconfig
import { useState } from 'react';                    // пакет из node_modules
import noop from '@/lib/format';                     // default-export
// noop здесь имя ЛЮБОЕ — мы решаем как звать default

export function PriceTag({ price }: { price: number }) {
  return <span>{formatPrice(price)}</span>;
}

// === Импорт нескольких ===
import { formatPrice, formatDate } from '@/lib';
import { fetchUser } from '@/lib/api';

// === Импорт + переименование ===
import { formatPrice as fp } from '@/lib';
console.log(fp(1500));        // используем под коротким именем

// === Импорт всего как объект ===
import * as utils from '@/lib';
utils.formatPrice(100);
utils.formatDate(new Date());

Реальный пример модулей в Next.js / React-проекте

главное
  • 01export = «отдаю наружу», import = «забираю себе»
  • 02Named: many per file, импорт ТОЧНО по имени `import { foo }`
  • 03Default: один на файл, имя при импорте свободное
  • 04Пути с ./ или ../ — относительные, без точки — пакет из node_modules
  • 05@/... в Next.js — alias на src/, настраивается в tsconfig.json
  • 06Barrel-файл (index.ts с re-export) — удобный коллектор для папки
  • 07as переименовывает: `import { x as y }` — берём x, называем y
проверь себя
01У вас `export default function MyComp() {}` в файле. Как импортировать?
02В чём разница между `import x from "react"` и `import x from "./react.js"`?
03Что делает `index.ts` с одним только `export * from "./file"`?
следующий урок: Async/await — код который ждёт