Библиотека и фреймворк: в чем разница и как выбрать

Библиотека и фреймворк: в чем разница и как выбрать Полезное

Библиотека (library) — это готовый код, который твоя программа вызывает сама, когда он нужен. Фреймворк (framework) — это каркас приложения, который управляет ходом работы программы и сам вызывает твой код в заранее определенных местах. Короткая формула различия: ты вызываешь библиотеку, фреймворк вызывает тебя. Этот принцип называют инверсией управления.

Ниже разберем различие на работающем примере на JavaScript, покажем, почему граница на практике размыта, и дадим порядок выбора инструмента под задачу.

Мини-словарь: четыре термина, которые путают

Термин Что это Пример
Библиотека Набор функций и классов под задачу; порядок вызовов определяет твой код Lodash, NumPy, date-fns
Фреймворк Каркас с жизненным циклом и правилами; твой код встраивается в его точки расширения Django, Angular, Spring
Инверсия управления (IoC) Принцип, при котором поток выполнения контролирует внешний код, а не твой Обработчик маршрута, который вызывает веб-фреймворк
Пакет Способ распространения кода (npm, PyPI, Maven), а не тип инструмента В пакете может лежать и библиотека, и фреймворк

Важно различать тип инструмента и способ его доставки: npm install ставит одинаково и библиотеку, и фреймворк. Разница в том, кто управляет программой после установки.

Главное отличие: кто кого вызывает

Признак Библиотека Фреймворк
Поток выполнения Контролирует твой код Контролирует фреймворк
Структура проекта Не навязывает Задает папки, соглашения, жизненный цикл
Как подключается твой код Ты вызываешь функции библиотеки Ты регистрируешь обработчики, классы, компоненты
Замена на аналог Обычно локальная правка Часто переписывание значительной части проекта
Порог входа Ниже: достаточно изучить нужные функции Выше: нужно понять архитектуру и соглашения

Размер инструмента не является критерием. Утверждение «библиотека — это маленький фреймворк» неточно: библиотека может быть огромной (как NumPy), а микрофреймворк — компактным (как Flask или Express). Решает не объем кода, а направление вызовов.

Пример на JavaScript: библиотека и мини-фреймворк в одном файле

Сначала полный рабочий пример. Его можно сохранить в файл demo.js и запустить командой node demo.js (подойдет Node.js 24 LTS или любая современная версия).

// Библиотека: набор функций, которые вызывает твой код
const textLib = {
  slugify(text) {
    return text
      .toLowerCase()
      .trim()
      .replace(/[^a-z0-9]+/g, "-")
      .replace(/^-|-$/g, "");
  },
};

// Мини-фреймворк: хранит обработчики и сам решает, когда их вызвать
function createApp() {
  const routes = new Map();
  return {
    get(path, handler) {
      routes.set(path, handler);
    },
    handle(path) {
      const handler = routes.get(path);
      if (!handler) return "404 Not Found";
      return handler({ path });
    },
  };
}

// 1. Библиотека: ты вызываешь ее, когда нужно
console.log(textLib.slugify("  Hello, Otus World! "));

// 2. Фреймворк: ты регистрируешь код, фреймворк вызывает его сам
const log = [];
const app = createApp();
app.get("/hello", (req) => {
  log.push("handler");
  return `Hi from ${req.path}`;
});
log.push("registered");
console.log(log);

console.log(app.handle("/hello"));
console.log(app.handle("/missing"));
console.log(log);

В консоли появится:

hello-otus-world
[ 'registered' ]
Hi from /hello
404 Not Found
[ 'registered', 'handler' ]

Разбор по шагам:

  1. textLib.slugify(...) вызывается в строке, которую написал ты. Когда и сколько раз вызвать функцию, решает твой код — это модель библиотеки.
  2. app.get("/hello", ...) не выполняет обработчик, а только передает его фреймворку. Поэтому после регистрации в журнале только registered.
  3. Обработчик срабатывает, когда фреймворк получил запрос в handle. Строка handler появляется в журнале только после этого.
  4. На неизвестный путь фреймворк отвечает 404 Not Found сам, твой код в этом не участвует. Это и есть поведение по умолчанию, которое задает каркас.

Пример упрощенный: настоящий веб-фреймворк еще слушает сетевой порт, разбирает HTTP-запрос, обрабатывает ошибки и middleware. Но направление вызовов в Express или Django устроено так же.

Колбэк еще не делает инструмент фреймворком

Частая путаница: раз библиотека принимает функцию-колбэк, значит, это фреймворк. Нет. Метод Array.prototype.sort принимает функцию сравнения и сам ее вызывает, но когда вызвать sort, решает твой код. Инверсия управления здесь локальная, в пределах одного вызова, а не на уровне всего приложения.

Заодно этот метод показывает, почему контракт библиотеки нужно читать. Неверный вызов:

const nums = [10, 1, 5];
nums.sort();
console.log(nums);

Результат неожиданный:

[ 1, 10, 5 ]

Без функции сравнения sort приводит элементы к строкам и сравнивает их как текст, поэтому "10" оказывается раньше "5". Исправление — передать функцию сравнения:

const nums = [10, 1, 5];
nums.sort((a, b) => a - b);
console.log(nums);

Теперь вывод правильный:

[ 1, 5, 10 ]

Почему граница размыта: React, Vue, Next.js

Деление на библиотеки и фреймворки — модель, а не строгая классификация. Многие инструменты сочетают оба подхода, а их авторы сами выбирают, как себя называть.

Инструмент Как позиционируется авторами Что происходит на практике
React Библиотека для пользовательских интерфейсов Сам вызывает твои компоненты при рендере, но роутинг и сборку выбираешь ты
Vue Прогрессивный фреймворк Можно подключить к одной странице как библиотеку или построить на нем все приложение
Angular Платформа и фреймворк Задает структуру проекта, внедрение зависимостей, роутинг, сборку
Next.js Фреймворк на основе React Добавляет к React файловый роутинг, серверный рендеринг, соглашения о папках
Express Минималистичный веб-фреймворк для Node.js Вызывает твои обработчики, но почти не диктует структуру
Lodash Библиотека утилит Только функции, которые вызываешь ты

Поэтому полезнее спрашивать не «как это называется», а «какую часть решений инструмент забирает у меня»: структуру папок, жизненный цикл, роутинг, работу с данными.

Виды фреймворков и библиотек

Фреймворки обычно делят по месту работы:

  • Фронтенд — интерфейс в браузере: Angular, Vue, Svelte.
  • Бэкенд — серверная логика, маршруты, работа с БД: Django, Spring, Express, ASP.NET Core.
  • Фулстек — клиент и сервер в одном проекте: Next.js, Nuxt.
  • Микрофреймворки — минимальное ядро, остальное добавляется расширениями: Flask, Express. Подходят и для небольших сервисов, и для крупных проектов, если команда готова сама собирать архитектуру.

Библиотеки различают по нескольким независимым признакам:

  • Стандартная и сторонняя. Стандартная поставляется с языком или средой (node:fs, модуль json в Python), сторонняя ставится менеджером пакетов.
  • Статическая и динамическая — это про компилируемые языки вроде C и C++. Статическая (.a, .lib) встраивается в исполняемый файл при сборке, динамическая (.so, .dll, .dylib) загружается при запуске и остается отдельным файлом. В JavaScript и Python такого деления в этом смысле нет, модули загружаются интерпретатором.
  • По лицензии. Открытый исходный код не означает «можно все»: MIT разрешает почти любое использование, а GPL накладывает условия на распространение производных программ. Лицензию проверяют до добавления зависимости.

Как выбрать: библиотека или фреймворк

Порядок, который помогает принять решение:

  1. Сформулируй задачу. Нужна одна функция (форматировать дату, валидировать форму) — начни с библиотеки. Нужно целое приложение с роутингом, формами, авторизацией — смотри на фреймворк.
  2. Оцени, готов ли ты принять правила. Фреймворк экономит время, если его соглашения подходят проекту. Если архитектура нестандартная, набор библиотек дает больше свободы.
  3. Проверь экосистему и поддержку. Дата последнего релиза, открытые проблемы, документация, совместимость с твоей версией языка.
  4. Оцени цену замены. Библиотеку за один модуль заменить легко, уход с фреймворка часто равен переписыванию.
  5. Проверь безопасность зависимостей. Каждая сторонняя библиотека — чужой код в твоем приложении. Фиксируй версии lock-файлом (package-lock.json), регулярно запускай npm audit и не подключай заброшенные пакеты ради одной функции.

Выводы

  • Библиотеку вызывает твой код, фреймворк сам вызывает твой код — это инверсия управления.
  • Размер инструмента не определяет его тип: решает, кто управляет потоком выполнения.
  • Колбэк в отдельном вызове (как в sort) не превращает библиотеку во фреймворк.
  • Граница размыта: React называют библиотекой, Next.js на его основе — фреймворком; полезнее оценивать, какие решения инструмент забирает у тебя.
  • Выбор зависит от задачи, готовности принять правила, поддержки проекта и цены замены.

Где применяется / связь с практикой

Освойте тему на практике

Разница между библиотекой и фреймворком становится понятной на практике, когда пишешь код руками: сначала на чистом языке, затем с библиотеками и, наконец, внутри фреймворка. Если хочешь пройти этот путь на JavaScript с разбором заданий, посмотри программу курса «JavaScript Developer. Basic». Бесплатно познакомиться с темами разработки можно на открытых уроках Otus.

FAQ

Можно ли использовать библиотеки внутри фреймворка?
Да, это обычная практика: например, в проекте на Angular или Django подключают библиотеки для дат, графиков или HTTP-запросов. Фреймворк задает каркас, библиотеки решают частные задачи внутри него.

Чем фреймворк отличается от SDK и платформы?
SDK — набор инструментов для разработки под конкретную систему (библиотеки, утилиты, документация, эмуляторы). Платформа — среда выполнения или экосистема, например Node.js или .NET. Фреймворк может входить в SDK или работать поверх платформы.

Нужно ли учить фреймворк сразу, минуя язык?
Лучше нет: без знания языка трудно отличить ошибку в своем коде от особенности фреймворка. Базовый синтаксис, функции, модули и асинхронность стоит освоить до первого фреймворка.

OTUS Журнал
Скидка 5% 14-20 сентября на курсы (popup)