Статьи

Как решить глобальную проблему зависимости модуля npm

Диспетчер пакетов Node (также известный как npm) предоставил веб-разработчикам легкий доступ ко многим удивительным модулям JavaScript и значительно упростил нашу жизнь при поиске и управлении зависимостями для наших приложений. Это также облегчает разработчикам создание и публикацию их собственных модулей , а это означает, что другие разработчики могут получить их с помощью простой npm install -g your-tool Это утопия! Правильно?

Эээ, на самом деле …

У нас есть небольшая проблема

Я никогда не скажу никогда не использовать опцию -g Есть несколько причин, по которым я считаю, что мы должны сократить использование нами глобальной установки модулей, особенно в случае инструментов сборки, тестирования или рисования, таких как Gulp , Karma , JSHint и многих других. В этой статье я буду ссылаться в первую очередь на Gulp, потому что он довольно популярен и забавно говорить, но если вам не нравится Gulp, просто мысленно замените его на то, что вы предпочитаете.

Прежде всего, глобальные модули не перечислены в качестве зависимостей в ваших проектах, даже если ваш проект зависит от них, что влечет за собой дополнительные шаги для других, использующих ваше приложение. Вы знаете, что вам нужно использовать Gulp, чтобы подготовить проект к работе, поэтому вы устанавливаете его глобально и используете его. Когда кто-то еще хочет начать работать или использовать ваш замечательный проект с открытым исходным кодом, он не может просто набрать npm install Вы заканчиваете тем, что бросали указания в свой файл README, говоря что-то вроде

Чтобы использовать этот проект, выполните следующие действия :

  • git clone
  • Запустите npm install
  • Запустите npm install -g gulp
  • Запустите gulp

Я вижу две проблемы с этим: во-первых, вы добавляете дополнительный этап глобальной установки Gulp, а во-вторых, вы запускаете gulp Я вижу дополнительный шаг, которого можно было бы избежать (глобальная установка Gulp), и я вижу, что пользователь должен знать, что ваше приложение использует Gulp для построения проекта. Эта первая проблема — основная, о которой я расскажу в этой статье, и хотя вторая проблема не так важна, вам придется обновить инструкции, если вы в конечном итоге переключите инструменты. Решение, которое я расскажу позже, должно решить обе эти проблемы.

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

  • Вы создали свой проект шесть месяцев назад и в то время использовали самую последнюю версию Gulp. Сегодня кто-то клонировал репозиторий вашего проекта и попытался запустить gulp Это потому, что человек, который клонировал ваш проект, использует либо более старую версию, либо более новую версию Gulp, которая имеет некоторые существенные различия.
  • Вы создали проект шесть месяцев назад, который использовал Gulp. С тех пор вы перешли к другим проектам и обновили Gulp на своем компьютере. Теперь вы возвращаетесь к этому старому проекту и пытаетесь запустить gulp Теперь вы вынуждены обновить процесс сборки для работы с новой версией Gulp, прежде чем вы сможете добиться большего прогресса в проекте, вместо того, чтобы откладывать его до более удобного времени.

Это потенциально очень вредные проблемы. Однако, как я уже говорил ранее, я бы не стал делать общее заявление о том, чтобы вы никогда не устанавливали что-либо глобально. Есть исключения.

Краткое примечание по безопасности

По умолчанию в некоторых системах для установки модуля npm требуются повышенные привилегии. Если вы обнаружите, что запускаете такие команды, как sudo npm install -g a-package Наше руководство для начинающих npm покажет вам, как.

Исключения из правила

Так что вы можете установить глобально? Проще говоря: от всего, что ваш проект не зависит. Например, у меня установлен глобальный модуль под названием local-web-server . Всякий раз, когда у меня есть только некоторые HTML-файлы, которые я хочу просмотреть в браузере, я просто запускаю wslocalhost:8000

Я также сталкиваюсь с ситуациями, когда я хочу минимизировать файлы JavaScript, которые не являются частью проекта или, по крайней мере, не являются частью проекта, где мне разрешено настроить формальный процесс сборки (по глупым «корпоративным» причинам). ). Для этого у меня установлен uglify-js, и я могу легко свернуть любой скрипт из моей командной строки за считанные секунды.

Решение

Теперь, когда мы знаем, где могут возникнуть проблемы, как мы можем их предотвратить? Первое, что вам нужно сделать, это удалить этот -g Вы должны заменить это на --save-devnpm install Это только решает одну из незначительных проблем, которые я упомянул, но это только начало.

Что вам нужно знать, так это то, что при локальной установке зависимости, если у нее есть какие-либо сценарии, предназначенные для запуска из командной строки, они будут помещены в ./node_modules/.bin/ Итак, прямо сейчас, если вы просто устанавливаете Gulp локально, вы можете запустить его, введя ./node_modules/.bin/gulp Конечно, никто не хочет вводить все это. Вы можете исправить это с помощью скриптов npm .

Внутри вашего файла package.jsonscripts

 {
    ...
    "scripts": {
        "gulp": "gulp"
    }
}

Теперь вы можете запустить npm run gulp Сценарии npm будут искать локальную копию исполняемой команды в каталоге ./node_modules/.bin/PATH Если вы хотите, вы можете даже передать другие аргументы в Gulp, добавив --npm run gulp -- build-devgulp build-dev

Это отстой, что вам все равно нужно вводить больше, чем если бы вы использовали Gulp в глобальном масштабе, но есть два пути решения этой проблемы. Первый способ, который также решает одну из проблем, которые я поднял ранее, — это использовать сценарии npm для создания псевдонимов. Например, вам не обязательно привязывать ваше приложение к Gulp, чтобы вы могли создавать сценарии, которые запускают Gulp, но не упоминают Gulp:

 {
    ...
    "scripts": {
        "build": "gulp build-prod",
        "develop": "gulp build-dev"
    }
}

Таким образом, вы можете сократить количество звонков в Gulp и сделать ваши сценарии общими. Сохраняя их универсальными, вы можете прозрачно удалить Gulp в любое время и заменить его чем-то другим, и никто не должен знать об этом (если только они не работают над процессом сборки, в этом случае они должны знать об этом уже и, вероятно, должны были быть частью Разговор о том, чтобы отойти от Гулпа). При желании вы даже можете добавить туда скрипт postinstallnpm install Это бы немного очистило ваш README. Кроме того, используя сценарии npm, каждый, кто клонирует ваш проект, должен иметь простую и немедленную документацию обо всех процессах, которые вы запускаете в своем проекте, прямо в файле package.json

В дополнение к использованию сценариев npm есть еще одна хитрость, которая позволит вам использовать ваши локальные установки инструментов командной строки: относительный PATH Я добавил ./node_modules/.bin/ Я узнал этот трюк из комментария к другому посту, который я написал (спасибо Габриэлю Фалькенбергу ).

Эти приемы не обязательно заменяют каждую ситуацию, в которой вы хотите использовать что-то вроде Gulp, и для их настройки требуется немного усилий, но я считаю, что рекомендуется включать эти инструменты в список ваших зависимостей. Это предотвратит конфликт версий (что является одной из основных причин менеджеров зависимостей в первую очередь) и поможет упростить шаги, необходимые для выбора вашего проекта.

Идти выше и дальше

Это может быть немного чрезмерно, но я также считаю, что Node и npm — это зависимости для вашего проекта, которые имеют несколько разных версий, которые могут конфликтовать. Если вы хотите быть уверены, что ваше приложение будет работать для ВСЕХ, то вам нужен какой-то способ, чтобы убедиться, что у пользователя также установлены правильные версии Node и npm.

Вы можете установить локальные копии Node и npm в свой проект! Это не делает все хорошо и модно, хотя. Во-первых, Node не одинаков в каждой операционной системе, поэтому каждому человеку все равно нужно убедиться, что он загружает тот, который работает с их операционной системой. Во-вторых, даже если бы существовал способ установить универсальный узел, вам необходимо убедиться, что у каждого пользователя есть простой способ доступа к узлу и npm из командной строки, например, чтобы каждый добавил путь к локальной копии. узла и npm к их PATH Нет простого способа гарантировать это.

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

Последнее слово

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