Прямой ответ
Пакет с компонентами содержит только собранные файлы, а общие зависимости объявляются внешними, поэтому пакет не дублирует библиотеку, уже установленную в приложении.
| Что объявляется | Где указывается |
|---|---|
| Состав пакета | Перечень публикуемых файлов |
| Общие зависимости | Как внешние, без включения в пакет |
| Точка входа | Основной файл пакета |
| Версия | По правилу semver |
{ "name": "@acme/ui", "version": "1.0.0",
"peerDependencies": { "vue": "^3.4" },
"files": ["dist"] }
Общая библиотека объявляется внешней, поэтому приложение использует одну копию вместо двух. О публикации пакета — в статье про npm publish.
Состав пакета и публикуемые файлы
Пакет содержит только файлы, необходимые для использования компонентов, поэтому исходники и примеры в пакет не включаются.
Собранные файлы. В пакет включается результат сборки, поэтому потребитель получает готовые компоненты без сборки на своей стороне.
Исходники и примеры. Не включаются в пакет, поэтому объём публикации не содержит файлы, не используемые потребителем.
Перечень файлов. Задаётся явно, поэтому случайное включение файла при изменении структуры не происходит.
Практическое следствие: публикация без явного перечня файлов включает каталог с исходниками, поэтому объём пакета растёт, а содержимое содержит файлы, не предназначенные для потребителя.
Отдельный аспект — проверка содержимого перед публикацией. Состав пакета проверяется до выпуска, поэтому лишний файл обнаруживается до того, как версия станет доступной потребителю.
Внешние зависимости и дублирование библиотек
Общая библиотека объявляется внешней, поэтому приложение использует одну копию, а не отдельную копию внутри пакета.
Внешняя зависимость. Объявляется как требование к приложению, поэтому библиотека не включается в состав пакета.
Одна копия библиотеки. Приложение устанавливает библиотеку один раз, поэтому пакет и приложение используют одну копию.
Версия зависимости. Диапазон версий задаётся явно, поэтому несовместимая версия не устанавливается вместе с пакетом.
Практическое следствие: включение общей библиотеки в состав пакета приводит к двум копиям в приложении, поэтому объём загрузки растёт, а состояние, разделённое между копиями, расходится.
Сборка и точка входа
Точка входа определяет, какой файл загружается при импорте пакета, поэтому состав экспорта задаётся явно.
Основная точка входа. Указывает файл с экспортом компонентов, поэтому импорт пакета загружает ожидаемый файл.
Состав экспорта. Перечень доступных компонентов задаётся явно, поэтому внутренний компонент не становится частью публичного интерфейса.
Стиль компонентов. Файл стилей поставляется вместе с пакетом, поэтому оформление применяется без отдельной настройки потребителем.
Практическое следствие: экспорт всех файлов каталога делает внутренние компоненты частью публичного интерфейса, поэтому изменение внутреннего компонента нарушает работу потребителя.
О нумерации версий — в статье про semver; о структуре системы — в статье про дизайн‑систему.
Практика: публикация библиотеки компонентов
1. Задайте явный перечень публикуемых файлов. Случайное включение исходников не происходит.
2. Объявите общие библиотеки внешними. Приложение использует одну копию вместо двух.
3. Укажите диапазон версий внешних зависимостей. Несовместимая версия не устанавливается вместе с пакетом.
4. Задайте точку входа явно. Импорт пакета загружает ожидаемый файл.
5. Ограничьте состав экспорта публичными компонентами. Внутренний компонент не становится частью интерфейса.
6. Поставляйте файл стилей вместе с пакетом. Оформление применяется без отдельной настройки.
7. Проверяйте содержимое пакета перед публикацией. Лишний файл обнаруживается до выпуска версии.
Рекомендации:
- Не включайте общие библиотеки в состав пакета. Две копии в приложении увеличивают объём загрузки и расходятся по состоянию.
- Не экспортируйте все файлы каталога. Изменение внутреннего компонента нарушает работу потребителя.
- Не публикуйте исходники и примеры. Объём пакета растёт без пользы для потребителя.
- Проверяйте состав пакета до каждой публикации. Лишний файл обнаруживается до того, как версия станет доступной.
- Пересматриваем состав экспорта при добавлении компонента. Новый публичный компонент добавляется в перечень явно.
Практический сценарий: приложение загружало две копии библиотеки
Контекст: после подключения библиотеки компонентов объём загрузки приложения вырос, а состояние, общее для компонентов, расходилось между частями интерфейса.
- Диагностика. Проверка зависимостей показала, что библиотека компонентов включала общую библиотеку в состав пакета. Приложение устанавливало ту же библиотеку отдельно, поэтому в загрузке присутствовали две копии, а состояние, разделяемое компонентами, создавалось в каждой копии отдельно.
- Причина. Общая библиотека не была объявлена внешней при сборке пакета, поэтому она попала в публикуемый состав вместо объявления как требование к приложению.
- Действия. (а) Объявили общую библиотеку внешней с указанием диапазона версий, чтобы пакет не включал её в состав; (б) пересобрали пакет и убедились, что библиотека отсутствует в публикуемых файлах; (в) задали явный перечень публикуемых файлов, чтобы исходники и примеры не попадали в пакет; (г) ограничили состав экспорта публичными компонентами, чтобы внутренние не стали частью интерфейса; (д) проверили содержимое пакета перед публикацией и обновили версию в приложении, убедившись, что загрузка содержит одну копию библиотеки.
- Результат. Приложение использует одну копию общей библиотеки, поэтому объём загрузки сократился, а состояние компонентов совпадает между частями интерфейса.
Вывод: включение общей библиотеки в состав пакета приводит к двум копиям в приложении, поэтому общие зависимости объявляются внешними с указанием диапазона версий. Проверка содержимого пакета перед публикацией обнаруживает лишний файл до выпуска версии.
FAQ
Что включать в пакет с компонентами? Собранные файлы и файл стилей. Исходники и примеры в публикуемый состав не включаются.
Почему объявлять общие библиотеки внешними? Приложение использует одну копию. Включение библиотеки в пакет приводит к двум копиям и расхождению состояния.
Как ограничить публичный интерфейс пакета? Явным составом экспорта. Экспорт всех файлов каталога делает внутренние компоненты частью интерфейса.
Зачем проверять содержимое перед публикацией? Лишний файл обнаруживается до того, как версия станет доступной потребителю.
Источники: npm publish, Semantic Versioning, npm package.json — ссылки в шапке.