Обрезать жир: советы по уменьшению размера пакета 🏋️

Легко добавить в проект множество пакетов npm. Не менее легко добавить их так много, что сборка, загрузка и выполнение пакета займет целую вечность. В реальном мире это приводит к плохому пользовательскому опыту или, что еще хуже, к полной потере пользователей.

В эти выходные у меня было свободное время, и я провел рефакторинг своего личного сайта, избавившись от ненужных мне пакетов и получив из этого пакет проекта:

public/index.853702c4.js                        282.07 KB  1.49s
├── /react-dom/cjs/react-dom.production.min.js  257.67 KB   48ms
├── /popmotion/dist/popmotion.es.js              62.27 KB   16ms
├── /popmotion-pose/dist/popmotion-pose.es.js    33.59 KB   66ms
├── /stylefire/dist/stylefire.es.js                 25 KB    7ms
├── /pose-core/dist/pose-core.es.js              21.74 KB    7ms
├── /react-pose/dist/react-pose.es.js            21.67 KB   85ms
├── /@emotion/stylis/dist/stylis.browser.esm.js  19.88 KB    4ms
├── /@popmotion/popcorn/dist/popcorn.es.js       17.37 KB    7ms
├── src/js/legos.js                              16.08 KB  318ms
└── /react-inlinesvg/esm/index.js                14.52 KB  207ms
└── + 79 more assets
Вход в полноэкранный режим Выход из полноэкранного режима

К этому: ✨

public/index.1d2e670f.js                         53.59 KB  348ms
├── /preact/dist/preact.module.js                31.56 KB   19ms
├── /@ctrl/tinycolor/dist/module/index.js        19.45 KB    5ms
├── /preact/compat/dist/compat.module.js         17.13 KB   18ms
├── /react-meta-tags/lib/meta_tags.js             9.39 KB   64ms
├── /@ctrl/tinycolor/dist/module/format-input.js  7.68 KB    8ms
├── src/js/app.js                                 7.52 KB  139ms
├── /preact/hooks/dist/hooks.module.js            7.25 KB   21ms
├── /@ctrl/tinycolor/dist/module/conversion.js    6.44 KB   76ms
├── /react-meta-tags/lib/utils.js                 5.88 KB    4ms
└── /react-meta-tags/lib/meta_tags_context.js     5.07 KB    3ms
└── + 25 more assets
Войти в полноэкранный режим Выйти из полноэкранного режима

1. Используйте меньшие библиотеки ✂️

Это относится только к проектам на базе React, но самый простой способ вырезать значительный кусок из вашего пакета — поменять React на Preact. Существуют руководства, позволяющие выполнить этот процесс в несколько шагов, а благодаря слою совместимости preact-compat вы, скорее всего, не заметите разницы (за исключением значительно меньшего размера пакета!).

Кроме того, внимательно посмотрите на свои зависимости и решите, действительно ли вам нужны все функции, которые они предоставляют. Даже небольшие пакеты могут со временем накапливаться. Такие инструменты, как bundlephobia, помогают найти более компактные альтернативы библиотеке с аналогичным API.

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

2. Переписать код, перегруженный библиотеками 🗑.

Пока эмоции 👩🎤

После использования bundlephobia для замены некоторых библиотек и внесения небольших изменений, чтобы все работало, я понял, что не было веской причины, почему мне вообще нужны некоторые из них. Очевидно, что это актуально только в каждом конкретном случае, но наименьшая библиотека, влияющая на размер вашего пакета — это отсутствие библиотеки вообще!

Например: Я использовал emotion для стилизации компонентов, но это было излишеством для такого маленького проекта. Не было веской причины, почему я должен был сохранить его, поэтому я просто выбросил его в пользу старомодного CSS и позволил пакету позаботиться об этом.

Некоторую логику, которая полагалась на props для определения цвета стилизованного компонента, нужно было переписать, но это было легко сделать с помощью переменных CSS. Это:

const Brick = styled.div`
  .child-class {
    background: ${props => darken(0.08, props.color)};
  }
`;

<Brick color="#fff">
  {children}
</Brick>
Вход в полноэкранный режим Выход из полноэкранного режима

Который использовал и @emotion/styled, и polished, был переписан для использования гораздо меньшей библиотеки цветовых утилит:

const color = new TinyColor(props.color).darken(80).toString();

const cssVars = {
  '--color-1': color
};

<div style={cssVars} className="brick">
  {children}
</div>
Войти в полноэкранный режим Выход из полноэкранного режима

В сочетании с некоторыми CSS:

.brick .child-class {
  background: var(--color-1);
}
Войти в полноэкранный режим Выход из полноэкранного режима

И результирующее поведение идентично! Удаление эмоций значительно сократило пакет. Следующим по значимости было избавление от библиотеки, которая была добавлена для работы с анимацией.

Библиотека анимации вылетает в трубу 💨.

Framer Motion (ранее react-pose) — это мощная библиотека анимации. Но в моем случае слишком мощная. Я добавил ее, чтобы поиграть с перемещением элементов, но она раздувала пакет проекта для простой анимации входа.

В итоге я заменил компонент motion на класс для применения CSS transform и useEffect для удаления класса после задержки. Новое поведение очень похоже на то, что было раньше, и оно определенно достаточно близко, чтобы оправдать удаление такой массивной зависимости (почти 100 кб!).

3. Всегда трясти деревья 🌳

Деревотрясение — не новая концепция, и все современные бандлеры поддерживают ее. Самый простой пример — вместо того, чтобы импортировать целую массивную библиотеку, например, lodash:

import lodash from 'lodash';

const number = lodash.random(0, 10); 
Войти в полноэкранный режим Выйти из полноэкранного режима

Использовать древовидно-трясущуюся библиотеку, которая позволяет импортировать только то, что вам нужно:

import random from 'lodash-es/random';

const number = random(0, 10); 
Войти в полноэкранный режим Выйти из полноэкранного режима

Таким образом, ваш пакетник может игнорировать неиспользуемые части библиотеки и включать только то, что необходимо. Однако не все библиотеки поддерживают такую возможность; разумно искать те, которые поддерживают.

Часто анализируйте пакеты 🔍.

Всегда полезно отслеживать эти вещи с течением времени, чтобы производительность не падала. Parcel, который я использовал для этого проекта, имеет полезный анализатор пакетов (аналогичный анализатору Webpack), который дает хороший визуальный обзор пакетов проекта. Это особенно полезно для выявления мертвого кода из пакетов, которого можно было бы избежать с помощью tree-shaking. Существует также множество инструментов, которые можно интегрировать с CI для обеспечения соблюдения размера пакета.

Конечный результат ⚡️

Теперь сборка этого проекта занимает меньше секунды, а размер gzipped-пакета уменьшился с ~150 кб до всего 18 кб! Страница загружается значительно быстрее, а процесс разработки стал намного более плавным.

Надеюсь, эти базовые понятия оказались полезными, пожалуйста, поделитесь советами, которые я не осветил!

Оцените статью
Procodings.ru
Добавить комментарий