Мы тонем в зависимостях, и нам это нравится
- 10 июля 2020

Дату основания города принято считать с первого заложенного камня. Начало фронтенд проекта в 2020 можно считать с выполнения npm install
. И точно так же, как и в бурно растущем городе, обрастающем как крупными проспектами, так и мелкими переулками, в проект попадают новые пакеты, за которыми следуют пакеты поновее. Вот только если местные жители знают каждую улочку рядом с домом, большинство из нас понятия не имеет, что попадает в папку node_modules/
.
Мы можем бесконечно спорить о стилях и архитектуре, но остаёмся беспомощными и беззащитными, когда сборка свежеобновленного проекта падает из-за протеста одного разработчика или же просто из-за ошибки автора пакета. Куда хуже, когда одна из зависимостей оказывается с неприятным сюрпризом в виде бэкдора.
Насколько вкусный сыр в мышеловке?
Программисты очень сильно любят готовый код. Не тот, что они писали ночами к горящему дедлайну (хотя к нему у них тоже отношение по-особому теплое), а тот, который уже давно написан и протестирован кем-то другим, и в довесок усыпан звездочками на гитхабе.
А ещё программисты не любят велосипеды и при первой же возможности переводят их на другой фреймворк или даже язык (но это всё равно байки).
Особенно популярные пакеты кроме уже готового кода предоставляют в подарок пропуск в собственную экосистему, что резко увеличивает шансы найти решение очередной проблемы или нанять разработчика, который уже знаком с немалой частью проекта, описанной в package.json
.
Поэтому в теории npm — идеальное место для идеального кода.
Но это не так
Эта фраза вынесена в заголовок и выделена жирным, хотя ни для кого не секрет, что идеального кода там нет, а я просто нагоняю пафос. Однако насколько именно этот код далёк до совершенства и должен ли он к нему стремиться?
Всё же, что не так с нашим списком зависимостей?
Мы теряем контроль
Количество пакетов в node_modules/
уже исчисляется тысячами, порой для этого достаточно установить всего один. Верить в то, что обновление одной библиотеки на n-ном уровне вложенности не уронит проект с каждым выполненным npm install
всё труднее. И когда это произойдет, нам останется только смотреть на падающие сборки и комментарии на гитхабе.
Порой необходимая функциональность нашей библиотекой просто не поддерживается. Ещё хуже, если она вообще не входит в планы и/или идеологию ее мейнтейнеров. Остается только заполнять пулреквест, который может так и не попасть в мастер, или делать форк и поддерживать его самостоятельно, теряя плюсы готового кода (кстати, форк почему-то выбирают реже).
Мы грузим слишком много
Мегабайтные бандлы уже не пугают так сильно, как должны. При этом весь код, что туда запакован, не решает всех проблем нашего проекта. Более того, часть кода решает проблемы вообще не нашего проекта. Так как про наши проблемы автор библиотеки не знает, да и знать не должен, за гибкость в использовании приходиться платить лишними килобайтами.
Как сделать лучше?
Подключая новый пакет, стоит понимать, какую именно проблему мы собираемся решить перед тем, как создать несколько новых. Если добавление зависимости обусловлено в основном тем, что про неё много пишут в Твиттере — это плохой подход.
Узнать что именно мы грузим
Код lodash/debounce
занимает около 130 строк и поддерживает 3 параметра, про которые в большинстве случаев можно даже и не знать. Этот метод покрывает как можно больше случаев и настолько раздут, что lodash/throttle
использует его же. В основной массе проектов потребность в отложенном выполнении кода можно закрыть простой реализацией в 7 строк.
В добавок, кроме действительно полезных функций, lodash
предоставляет методы map
, filter
, some
и многие другим, которые уже давно являются частью JavaScript и неизменно присутствуют в ежегодных топах «10 методов массивов, про которые вы не слышали». Вместо изучения документаций многочисленных библиотек стоит хорошо узнать возможности, предоставляемые браузерами.
Поиск значений через indexOf === -1
легко заменяется на includes/startsWith/endsWith
, а вместо lodash/get
можно использовать chaining-operator.
Настроить сборщик
Полезно заранее определить внутри команды, какой размер бандла считать приемлемо средним, а какой — неприлично большим, выставив соответствующий бюджет. Для обычных приложений будет более интересна другая характеристика — время загрузки, которую тоже можно ограничить:
"size-limit": [
{
"limit": "60 s",
"path": "dist/app.js"
}
]
Если приложение грузится дольше минуты, мы вовремя узнаем об этом!
Чтобы этот момент не наступал как можно дольше, стоит отслеживать крупные модули с помощью webpack-bundle-analyzer
:

Классические локали moment.js
, которые высасывают бюджет бандла просто потому, что мы забыли их отключить.
Также некоторые из зависимостей в проекте могут использовать одну и ту же библиотеку, но подключать ее по-разному, из-за чего код в бандле дублируется. Например, один пакет подключает lodash
, другой использует lodash-es
, в итоге в бандле — оба. Правильно настроив сборщик, можно избавиться от лишних килобайт.

Одна и та же зависимость может подключаться в нескольких версиях, в примере ниже выделены core-js 1.2.7, 2.5.3 и 3.3.4.

Большинство популярных библиотек имеют окно для оптимизаций, которые достаточно просто применить, чтобы минимизировать их вклад в размер бандла. Полный список — в репозитории Google Chrome Labs. Больше советов по увеличению производительности — на канале Ивана Акулова.
Как контролировать список зависимостей?
Стоит признаться самим себе, что нам не нужно столько оболочек и посредников между программистом и кодом.
- Нам не нужно тянуть весь
lodash
ради трёх условных функций, две из которых уже являются частью языка. - Нам не нужен
moment
со всеми его зонами только ради того, чтобы посчитать сколько времени прошло между двумя датами. - Нам не нужен jQuery для смены классов у нескольких элементов.
И нам точно не нужен лендинг на React.js, просто потому что всё остальное написано на нём же. Конечно, не стоит полностью изолироваться от мира и npm, но стоит чаще задумываться о том, что мы ставим в проект, и действительно ли нужно именно это.
Однако современный JavaScript достаточно выразителен, чтобы заменить им устаревшие библиотеки:
- GitHub избавился от jQuery, оставив нативные функции и полифилы.
- Недавно вышедший почтовый клиент hey раздаёт обычный HTML, лишь прогрессивно улучшая его.
Лоадеры не скроют бесконечную загрузку сайта в метро, а анимации не спрячут «прыгающий» контент. Если продукт не несёт ценности для пользователя, он так и не увидит, насколько плавно организованы переходы между страницами, так как не уйдёт дальше первой.
«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.
Читать дальше

AOT против JIT-компилятора: что лучше для разработки на Angular?
Angular — один из самых популярных фреймворков для фронтенда — предлагает два подхода к компиляции: предварительная компиляция и динамическая компиляция во время выполнения. Оба метода играют важную роль в оптимизации приложений на Angular и повышении их производительности. В этом материале мы рассмотрим различия между ними, их преимущества и разберёмся, когда стоит использовать каждый из подходов.
- 25 мая 2025

Динамические формы в Angular 19: пошаговое руководство
Формы — неотъемлемая часть большинства веб-приложений: будь то регистрация, ввод данных или опросы. Модуль реактивных форм в Angular отлично подходит для создания статичных форм, но во многих случаях требуется, чтобы форма могла динамически адаптироваться в зависимости от действий пользователя или внешних данных.
В этой статье мы рассмотрим, как создавать динамические формы с использованием автономных компонентов в Angular 19, применяя модульный подход, который избавляет от необходимости использовать традиционные модули Angular. В сопроводительном репозитории на GitHub для оформления форм используется Tailwind CSS, однако в статье внимание сосредоточено исключительно на логике динамических форм. Tailwind и связанные с ним настройки намеренно не включены в примеры, чтобы сохранить акцент на основной теме.
- 25 мая 2025

Как обнаружить изменения в Angular: пошаговая инструкция
Как разработчики на Angular, мы нередко задумываемся, как фреймворк отслеживает изменения в данных и затем отображает их во вьюхе. Этот процесс называется стратегией обнаружения изменений в Angular. В этом материале мы разберёмся, как это работает, и научимся выбирать подходящую стратегию для разных сценариев.
- 24 мая 2025

Компоненты в Angular 18: пошаговое руководство
Angular развивается стремительно, и с выходом версии 18 появились новые возможности, которые разработчики могут использовать в своей работе. Одним из ключевых изменений в Angular 18 стало удаление традиционного файла app.module.ts — ему на смену пришли standalone-компоненты. Если вы только начинаете работать с Angular или переходите с более ранней версии, это пошаговое руководство поможет вам разобраться в базовых принципах компонентов в Angular 18. Независимо от вашего уровня — новичок вы или опытный разработчик — этот туториал покажет, как создавать, управлять и эффективно использовать компоненты в Angular.
- 19 мая 2025

Полное руководство по Angular @if
Одно из самых заметных нововведений в Angular — это встроенный синтаксис для управляющих конструкций, который появился в версии 17. Он решает одну из самых частых задач, с которой сталкивается каждый разработчик: показывать или скрывать элементы на странице в зависимости от условия. Раньше для этого использовали привычную структурную директиву *ngIf
. Теперь у нас есть более современная альтернатива — синтаксис @if
, часть нового подхода к управлению шаблоном.
В этом гайде мы сравним оба варианта, разберёмся, чем @if
лучше, и покажем, как можно перейти на него автоматически. Также поговорим об одной распространённой ошибке — о том, как не стоит использовать @if
вместе с пайпом async
.
- 18 мая 2025

Модули Angular для организации кода и ленивой загрузки
Модули — один из ключевых инструментов Angular для построения масштабируемых и поддерживаемых приложений. В этой статье мы подробно рассмотрим:
- что такое модули в Angular;
- зачем они нужны;
- как их использовать для структурирования кода;
- как реализовать «ленивую» загрузку модулей;
- и чем отличаются Feature, Core и Shared модули.
Если вы только начинаете изучать Angular или хотите углубить свои знания, эта статья поможет вам лучше понять, как правильно организовать архитектуру Angular-приложения.
- 12 мая 2025

Навигация в Angular: RouterLink, Router.navigate и Router.navigateByUrl
Директива RouterLink
позволяет настраивать переходы между маршрутами прямо в шаблоне Angular. А методы Router.navigate
и Router.navigateByUrl
, доступные в классе Router
, дают возможность управлять навигацией программно — прямо из кода компонентов.
Разберёмся, как работают RouterLink
, Router.navigate
и Router.navigateByUrl
.
- 11 мая 2025

Полное руководство по Lazy Loading в Angular
Если вы создаёте большое Angular-приложение, вам наверняка важно, чтобы оно загружалось быстро. Представьте, что вы устраиваете вечеринку и хотите подавать закуски не сразу, а по мере прихода гостей, чтобы не перегрузить кухню. «Ленивая» загрузка в Angular работает примерно так же: вместо того чтобы загружать всё приложение целиком сразу, вы подгружаете только те части, которые нужны — и только когда они нужны.
В этом пошаговом руководстве мы разберём, как реализовать lazy loading в Angular.
- 10 мая 2025

Все (ну или почти все) способы автоматически перезагрузить страницу раз в N секунд
Иногда страницу нужно просто перезагрузить. Полностью. Не компонент, не блок, а именно целиком. Без обсуждений, без лишней логики. Например, чтобы:
- экран с результатами обновлялся каждые 10 секунд;
- интерфейс на стенде показывал последние данные без кнопок;
- страницы в интранете не устаревали, пока никто не смотрит.
Это можно сделать в любой связке: HTML, JS, Python, PHP, Go, Node.js — не важно. Ну и если говорить совсем прямо, то совсем разных способов всего три, а остальное просто вариации.
- 5 мая 2025

Поиск с конца массива в JavaScript: findLast и findLastIndex в JavaScript
С недавних пор в JavaScript появились два полезных метода для массивов: findLast
и findLastIndex
. Они делают то же, что и привычные find
и findIndex
, только проходят массив с конца.
- 5 мая 2025