Pull to refresh

Comments 57

Обычная установка yarn: 19s
Установка через yarn --pnp: 3s
Перед измерением была проведена одна холодная установка, чтобы все нужные модули уже были в кеше.

То есть теперь установка будет занимать 19+3 (прогрев кэша и установка из кэша) секунды, вместо 19 (напомню, что скачанные модули кэшируются в любом случае). О — оптимизация.


Плюс теперь надо весь тулинг переписывать. Сэкономили человеко-часы, ничего не скажешь.

То есть теперь установка будет занимать 19+3

Не совсем так. 19 секунд занимает копирование файлов из кеша в node_modules, по сравнению с 3 секундами на создание файла с маппингами. Если вы уже однажды установили модули и их версии сохранились в yarn.lock, то установка этого проекта c --pnp будет всегда занимать ~3 секунды.

Если я уже однажды устанавливал модули и они сохранились в кэше, то повторная установка займет… ну может не 3 секунды, а уже 6, но разница непринципиальная.

Ну вы же сами цитировали:


Обычная установка yarn: 19s

Не 3, не 6, а целых 19 секунд занимает тупое копирование файлов...

Нет, это с разрешением зависимостей, скачиванием файлов (и их распаковкой).

Судя по процитированному вами фрагменту, эти оба времени замерялись уже после одного холодного запуска, то есть при полном кеше. Так что скачивание файлов сюда точно не входило.

Окей, был неправ, признаю и приношу извинения. Выигрыш во времени установки действительно есть.

mayorovp правильно говорит. Скачивания файлов и распаковки здесь не происходит. В кеше они уже хранятся в распакованном виде.


Для чистоты эксперимента я повторил эти операции с флагом --offline и отключенным интернетом, цифры остались те же.

CI система, да и вы вызывают запуск 10 раз на дню.
Так что экономия есть.
И еще как по мне килер фича: Отсутствие папочки с 10 — 50 — 100 мегабайт мелко нашинкованного ява-скрипта. А если у вас в работе 5-6 проектов?
Папка с проектами весит 7Гиг, вот это будет экономия.
100мб ??? Мелко плаваете у нас в проекте node_modules 700mb
А зачем? И в какой бандл они потом билдятся?
node_modules может не только для сборки фронта использоваться ;)
UFO just landed and posted this here
Во первых не нужно быть рутом. Во вторых большая гранулярность по версиям.
В третьих сайд-эффекты уменьшаются и четко контролируются версии.

Возможно есть еще какие соображения.
  1. Глобальная установка делает доступными только исполняемые команды, например: eslint, webpack и т.д. require('module-name') работать не будет
  2. Даже если исправить первый пункт, все равно останется проблема разных версий. Глобально можно установить только одну версию модуля, а из кеша можно смаппить несколько разных мажорных версий для разных проектов.

еще больше запутали логику
потом будут распутывать
потом распутывать нараспутывание
и т. д.

Очень странная мысль о том, что это как-то поможет CI. Откуда возьмётся локальный кеш-то? Сначала сборку у себя делает разработчик, потом один CI собирает билд, а другой CI раскатывает этот билд на сервера. Ни у одного из CI серверов при этом кеша может не быть, и обычно CI делается в контейнерах, где кеша точно не будет. Так что кому и чем это может помочь — загадка. Ну разве что разработчику локально.

У нас используется утилитка npm-cache, которая позволяет собрать кеш в архив и эти архивы монтировать на CI машинки. Утилита несколько заброшенная, но я её допиливал, если кому интересно.

И что, эти контейнеры еще и сбрасываются в начальное состояние перед каждой сборкой? Ну, хозяин-барин конечно, но не все же так делают.

Не сбрасываются, они каждый раз просто новые. Чтобы ничего не могло накопиться и повлиять на билд.
они похоже что то подобное будут делать, когда будет запущен yarn, он положит в свой кеш и потом оттуда будет отдавать зависимости

Предполагается, что у CI-системы есть кеш, который сохраняется между билдами. Например, в travis-ci можно включить сохранение кэша Yarn.


Рабочая директория билда всегда новая, а вот кэш из домашней директории пользователя может и сохраняться, ничего плохого в этом нет.

Так это можно делать и с node_modules. В чем профит?

node_modules содержит зависимости конкретно под этот проект, описанные в package.json. Если там что-то поменяется, кэширование node_modules билду только навредит. А глобальный кеш –универсальный, это просто локальная копия удаленного репозитория, без зависимости от того, что происходит с package.json.

Это же зависит от вашего инструмента для CI. Хотя странно, большинство точно умеют в кеш между разными заработало этапами процессов CI&CD

У node_modules есть замечательное преимущество — код импортируемых библиотек всегда под рукой, можно его посмотреть, поставить точку останова, подебажить и так далее. При новом подходе он будет храниться где-то далеко, и очень хорошо, если IDE сумеет найти код библиотек и обработать точки останова.
/home/user/.npm_cache/cookie/src
/home/user/project/coolstuff/node_modules/cookie/src

В чем разница для ide?

В том что второй находится в «окружении» проекта, первый же отдельно. Эти пути не настраиваются явно у вас в проекте.
UFO just landed and posted this here
я не исключаю, и любая иде/редактор позволяет искать внутри определенной папки. А поиск использования метода в иде обычно исключает «фиктивные папки» ибо это общеизвестны места «левого кода»

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


Ну и, чтобы два раза не вставать:

Отказ от директории node_modules – закономерный шаг, учитывая опыт других языков, где такого подхода не было изначально.
Это шаг назад, и после других языков, где библиотеки/фреймворки устанавливались глобально (а зависимости нужно было разрешать ручками) я был очень рад всегда иметь под рукой локальную копию всего нужного, которую всегда можно резетнуть и подтянуть автоматически.
Поддерживаю. Довольно часто* приходится лезть в node_modules.
_______
* по сравнению с теоретическим отсутствием необходимости вообще туда лезть
Для IDE это явно не проблема
в том же Ruby есть rvm, rbenv, папочка .bundle и со всеми вариантами IDE прекрасно работает
у rvm есть gemset, и IDE прекрасненько подтягивает нужный gemset и GOTO definition замечательно работает

Не вижу никаких проблем, почему IDE не справятся с таким же подходов в JS
А меня волнует — как можно будет бороться с подобными ошибками, когда приходится вручную править node-modules:
toster.ru/q/561727
Ну так там же файл не просто так дублируется, а из-за конфликта версий. Вот его-то и нужно устранять…
Ну и как устранить конфликт версий у двух typescript-зависимостей? Уж простите, я nodejs редко настраиваю, а беглый гуглинг по «nodejs устранить конфликт версий» ничего не дает.
На практике обычно форкнуть одну из них.
так, по идее, будет легче — один раз исправил и во всех проектах, которые эту ошибку той же версии используют, всё заработает, как надо.

Насколько я понимаю, проблема в том, что транзитивные зависимости тянут за собой разные версии тайпингов (что логично, разные мажорные версии обладают разным API).


Typescript схлопывает вложенные зависимости в плоский список и ломает вложенные тайпинги. Это проблема самого Typecscript и от способа доставки модулей не зависит.


Возможно, стоит зарепортить проблему им на Github. Я нашел очень похожую проблему, но там решения так и нет.

А можно зафорсить какую-то из зависимостей использовать другую версию своей зависимости?

В ситуации с Yarn — можно попробовать вручную отредактировать yarn.lock, все версии там прописаны. Если пользуетесь npm, аналогичное исправление package-lock.json теоретически тоже должно сработать

Работает.
Но только такие resolution'ы чреваты тем, что при каждом коммите придётся очень внимательно смотреть на изменения в `package-lock.json`, так как любой `npm install` это сбросит.
Хотя как времянка, когда PR в проект, который подобным образом фиксится, уже создан и просто ждёшь аппрува — вполне сгодится.

Добавлю, что это проблема не только Typescript, но и выбранного способа описания модуля у mongoose: они используют вариант declare module, который объявляет модуль в глобальном пространстве имен.

Не решение проблемы, но как вариант — форкнуть проект и опубликовать версию пакета для своих целей без проблемной папки?
Она ведь проблемная не сама по себе, а при соединении с другим пакетом
UFO just landed and posted this here
UFO just landed and posted this here

А почему бы не вызывать npm install && npm start из того места где вы сейчас вызываете npm start?

UFO just landed and posted this here

можете поделиться, что за хостинг? имхо очень странно что он не делает install самостоятельно

«Установка зависимостей отнимает большую часть времени сборки в CI-системах, поэтому ускорение этого шага благоприятно скажется на времени билда в целом.»
В самом деле? Вы либо попадаете в кеш докера, либо все равно вся качаете с нуля, потому что так работает докер, на сколько я знаю. Возможно я ошибаюсь.
COPY package.json.
COPY yarn.lock.
RUN yarn install --frozen-lockfile --ignore-optional

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


Новая инициатива минимизирует даже эти затраты.

Докер при каждом шаге создает промежуточные контейнеры, для кеширования и если входящие данные не меняються, тоесть если package.json не меняется, а у вас не должны при каждом обновлении меняться зависимости, то он пропускает эти шаги при следующих билдах, тоесть выиграш для CI там минимальный
Это сработает только если вы закешируете package.json отдельно от остальных исходников проекта. Так бывает не всегда, и в других ситуациях глобальный кэш придет на помощь.

Если вам удобнее настроить кастомную обработку package.json – дело ваше.
Согласен, ситуации бывают разные, но мы решили эту проблему таким образом. B мне казалось это очевидным и простым решением. Потэтому вызвало легкое недоумение, что у кого то есть такие проблемы в CI.
Sign up to leave a comment.

Articles