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
и отключенным интернетом, цифры остались те же.
Так что экономия есть.
И еще как по мне килер фича: Отсутствие папочки с 10 — 50 — 100 мегабайт мелко нашинкованного ява-скрипта. А если у вас в работе 5-6 проектов?
В третьих сайд-эффекты уменьшаются и четко контролируются версии.
Возможно есть еще какие соображения.
- Глобальная установка делает доступными только исполняемые команды, например: eslint, webpack и т.д.
require('module-name')
работать не будет - Даже если исправить первый пункт, все равно останется проблема разных версий. Глобально можно установить только одну версию модуля, а из кеша можно смаппить несколько разных мажорных версий для разных проектов.
еще больше запутали логику
потом будут распутывать
потом распутывать нараспутывание
и т. д.
У нас используется утилитка npm-cache, которая позволяет собрать кеш в архив и эти архивы монтировать на CI машинки. Утилита несколько заброшенная, но я её допиливал, если кому интересно.
И что, эти контейнеры еще и сбрасываются в начальное состояние перед каждой сборкой? Ну, хозяин-барин конечно, но не все же так делают.
Предполагается, что у CI-системы есть кеш, который сохраняется между билдами. Например, в travis-ci можно включить сохранение кэша Yarn.
Рабочая директория билда всегда новая, а вот кэш из домашней директории пользователя может и сохраняться, ничего плохого в этом нет.
Так это можно делать и с node_modules. В чем профит?
Это же зависит от вашего инструмента для CI. Хотя странно, большинство точно умеют в кеш между разными заработало этапами процессов CI&CD
/home/user/project/coolstuff/node_modules/cookie/src
В чем разница для ide?
Тем, что если при отладке одного проекта я где-то глубоко в коде чужого модуля понаставлю логгеры, хуки, заглушки и точки останова, то они вылезут при сборке какого-нибудь другого проекта, которых у меня может быть параллельно десяток в поддержке.
Ну и, чтобы два раза не вставать:
Отказ от директории node_modules – закономерный шаг, учитывая опыт других языков, где такого подхода не было изначально.Это шаг назад, и после других языков, где библиотеки/фреймворки устанавливались глобально (а зависимости нужно было разрешать ручками) я был очень рад всегда иметь под рукой локальную копию всего нужного, которую всегда можно резетнуть и подтянуть автоматически.
_______
* по сравнению с теоретическим отсутствием необходимости вообще туда лезть
в том же Ruby есть rvm, rbenv, папочка .bundle и со всеми вариантами IDE прекрасно работает
у rvm есть gemset, и IDE прекрасненько подтягивает нужный gemset и GOTO definition замечательно работает
Не вижу никаких проблем, почему IDE не справятся с таким же подходов в JS
toster.ru/q/561727
Насколько я понимаю, проблема в том, что транзитивные зависимости тянут за собой разные версии тайпингов (что логично, разные мажорные версии обладают разным API).
Typescript схлопывает вложенные зависимости в плоский список и ломает вложенные тайпинги. Это проблема самого Typecscript и от способа доставки модулей не зависит.
Возможно, стоит зарепортить проблему им на Github. Я нашел очень похожую проблему, но там решения так и нет.
В ситуации с Yarn — можно попробовать вручную отредактировать yarn.lock
, все версии там прописаны. Если пользуетесь npm, аналогичное исправление package-lock.json
теоретически тоже должно сработать
Но только такие resolution'ы чреваты тем, что при каждом коммите придётся очень внимательно смотреть на изменения в `package-lock.json`, так как любой `npm install` это сбросит.
Хотя как времянка, когда PR в проект, который подобным образом фиксится, уже создан и просто ждёшь аппрува — вполне сгодится.
В yarn можно через resolutions
https://yarnpkg.com/lang/en/docs/selective-version-resolutions/
Добавлю, что это проблема не только Typescript, но и выбранного способа описания модуля у mongoose: они используют вариант declare module
, который объявляет модуль в глобальном пространстве имен.
В самом деле? Вы либо попадаете в кеш докера, либо все равно вся качаете с нуля, потому что так работает докер, на сколько я знаю. Возможно я ошибаюсь.
COPY package.json.
COPY yarn.lock.
RUN yarn install --frozen-lockfile --ignore-optional
В этом треде уже объяснялось, что даже в идельном закешированном окружении остаются затраты на копирование файлов из кеша в проект.
Новая инициатива минимизирует даже эти затраты.
Если вам удобнее настроить кастомную обработку package.json – дело ваше.
Node.js без node_modules