Наличие project_name/node_modules в качестве символической ссылки?

Связано: одна папка node_modules для нескольких проектов

Если npm install -g все не рекомендуется, и я не хочу связывать отдельные модули, могу ли я символически связать <some project>/node_modules с общим каталогом, который будет использоваться несколькими проектами?


person prusswan    schedule 27.03.2016    source источник


Ответы (1)


Node отлично справляется с символическими ссылками. Как достичь этого, будет зависеть от некоторых ваших целей. Самое главное: какой опыт вы хотите предоставить другим разработчикам, которые загружают ваш проект(ы) из системы контроля версий?

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

В общем, я рекомендую не беспокоиться о дублирующихся зависимостях между проектами. «Исправление» этого не стоит затрат на обслуживание, которое включает в себя блокировку зависимостей (противоречащие потребности подпроектов) и необходимость в пользовательских инструментах в некоторых случаях для учета вашей пользовательской структуры.

Когда это предупреждение убрано, как нам это сделать? Самый простой способ — создать суперпроект, который инкапсулирует различные подпроекты. Подпроекты фактически наследуют зависимости суперпроекта.

superproject/
|-- node_modules/
|   +-- socket.io/
|-- package.json
|-- subprojectA/
|   |-- node_modules/
|   |   +-- browserify/
|   |-- package.json
|   +-- app/
|       +-- client.js
+-- subprojectB/
    |-- node_modules/
    |   +-- express/
    |-- package.json
    +-- lib/
        +-- server.js

Эта структура работает, как и следовало ожидать, файлы внутри подпроектов могут require() использовать свои собственные модули и любые из тех, что находятся в superproject/node_modules, но они не будут легко require() модули в своих родственных подпроектах (это все еще возможно сделать с помощью явных путей). Другими словами, client.js может require() браузерировать и socket.io без пути, но ему нужно будет использовать путь к require() экспрессу.

Важным аспектом этого является то, что npm выполняет поиск package.json и работает с модулями в каталоге node_modules как родственным этому файлу при установке и т. д. Это означает, что ваш текущий рабочий каталог должен быть superproject для установки в него модулей, если только в вашем подпроекте нет файла package.json.

person Seth Holladay    schedule 27.03.2016
comment
Дублирование зависимостей является серьезной проблемой, потому что файлы занимают довольно много места даже для очень маленьких проектов, а также приводят к косвенной трате полосы пропускания при настройке новых проектов, которые используют (в основном) те же зависимости. - person prusswan; 27.03.2016
comment
Я могу относиться к этим желаниям. Но я думаю, вы обнаружите, что тесное связывание различных проектов таким образом создает другое бремя. Тот, в котором вы не можете обновить зависимость, потому что проекту x требуется определенное поведение. Но вы действительно хотите/нужно обновить его, потому что проект y использует его по-другому и нуждается в чем-то новом. Раньше все модули npm были глобальными, эта практика прекратилась, потому что сообщество поняло, что оно того не стоит. nodejs.org/en/blog/npm /npm-1-0-global-vs-local-installation При всем при этом существуют способы создания псевдоглобальных модулей. - person Seth Holladay; 27.03.2016
comment
Суперпроект - гениальное решение! Большое спасибо. В моем случае я работаю над несколькими PHP-проектами Laravel, которые используют узел только для задач разработки (gulp). Gulp и require() работают только при локальной установке, но дублировать 200 МБ node_modules для каждого 5 МБ PHP-проекта совершенно неразумно, тем более что я сам не занимаюсь разработкой узлов. Суперпроект — единственное разумное решение, которое я нашел: у меня может быть папка laravel-5.2 с одной копией инструментов, необходимых для 5.2, вместе со всеми проектами 5.2 и так далее. Великолепно! - person Tobia; 06.07.2016
comment
@SethHolladay Люди уже сталкивались с этой проблемой, и она была успешно решена за всю историю разработки ОС. В любой ОС есть буквально сотни (если не тысячи) разделяемых библиотек, и несколько разных версий одной и той же библиотеки могут счастливо сосуществовать, просто используя простое правило — включать версию в имя библиотеки. Так что умный разработчик воспользовался бы конвенцией node_modules/[email protected]/library.js и тогда бы не пришлось биться об стены.... - person IVO GELOV; 11.09.2017
comment
@IVOGELOV несколько разных версий одной и той же библиотеки могут счастливо сосуществовать - верно, и npm тоже может это делать. Единственное отличие состоит в том, что npm предпочитает вкладывать зависимости в древовидный формат, когда это необходимо, вместо того, чтобы всегда размещать все в плоском виде и дублировать информацию о версии в идентификаторе модуля. Это лучше работает для локальных зависимостей, что рекомендуется. Чтобы заставить его работать с глобальными общими зависимостями, загрузчику модуля потребуется информация о версии в идентификаторе модуля. Но никто не хочет require('[email protected]'), потому что он принадлежит только одному месту: package.json. - person Seth Holladay; 30.09.2017
comment
@SethHolladay Я признаю, что моего опыта работы с NPM и Node недостаточно, поэтому, пожалуйста, простите меня, если мои слова звучат глупо. В Linux, когда вы устанавливаете новую версию библиотеки, старая версия не удаляется, но создается символическая ссылка (которая не содержит информации о версии в своем имени), указывающая на последнюю версию библиотеки. Однако, если вы обновляете библиотеку, текущая версия не сохраняется. Таким образом, потребители могут использовать последнюю версию (какой бы она ни была) через символическую ссылку или явно указать на нужную версию библиотеки. А задача загрузчика - проверить package.json - person IVO GELOV; 01.10.2017
comment
@SethHolladay и определите, нужна ли require или import определенная версия или какая из установленных в данный момент последняя. Мне также кажется нелогичным, что NPM отказывается работать, когда node_modules в папке проекта является символической ссылкой. - person IVO GELOV; 01.10.2017
comment
node_modules как символическая ссылка должна работать нормально. Я специально не проверял это, но если это не работает, это звучит как ошибка. Я не знаю ни одного варианта дизайна или ограничения, которое наложило бы ограничение, при котором node_modules не должно быть символической ссылкой. Тем не менее, возможно, npm наивно стирает его. Что касается проверки package.json, это задача загрузчика, это было бы неплохо. К сожалению, это не так. Однако звучит как хорошее решение, которое потенциально может быть реализовано в пользовательской среде. - person Seth Holladay; 02.10.2017
comment
Не перехватывать сообщение, но я столкнулся с аналогичной проблемой, см. мой пост SO здесь и попробовал создать символическую ссылку из внешнего каталога node-modules, которая помещает его в корень каталога моего проекта. Моя цель не в том, чтобы совместно использовать каталог node_modules для разных проектов, а в том, чтобы иметь дело с ограниченной по пространству средой Raspberry Pi с разделами на диске. - person Brad W; 23.12.2020