Должен ли я использовать node_modules для git при создании приложения node.js на Heroku?

368

Я следовал основным инструкциям по началу работы для node.js на Heroku:

https://devcenter.heroku.com/categories/nodejs

Эти инструкции не говорят вам создавать .gitignore node_modules, и поэтому подразумевают, что node_modules должны быть зарегистрированы в git. Когда я включаю node_modules в git, моё приложение запускается правильно.

Когда я последовал более сложному примеру:

https://devcenter.heroku.com/articles/realtime-polyglot-app-node-ruby-mongodb-socketio https://github.com/mongolab/tractorpush-server (источник)

Он поручил мне добавить node_modules в .gitignore. Поэтому я удалил node_modules из git, добавил его в .gitignore, а затем повторно развернул. На этот раз развернуто не удалось так:

-----> Heroku receiving push
-----> Node.js app detected
-----> Resolving engine versions
       Using Node.js version: 0.8.2
       Using npm version: 1.0.106
-----> Fetching Node.js binaries
-----> Vendoring node into slug
-----> Installing dependencies with npm
       Error: npm doesn't work with node v0.8.2
       Required: node@0.4 || 0.5 || 0.6
           at /tmp/node-npm-5iGk/bin/npm-cli.js:57:23
           at Object.<anonymous> (/tmp/node-npm-5iGk/bin/npm-cli.js:77:3)
           at Module._compile (module.js:449:26)
           at Object.Module._extensions..js (module.js:467:10)
           at Module.load (module.js:356:32)
           at Function.Module._load (module.js:312:12)
           at Module.require (module.js:362:17)
           at require (module.js:378:17)
           at Object.<anonymous> (/tmp/node-npm-5iGk/cli.js:2:1)
           at Module._compile (module.js:449:26)
       Error: npm doesn't work with node v0.8.2
       Required: node@0.4 || 0.5 || 0.6
           at /tmp/node-npm-5iGk/bin/npm-cli.js:57:23
           at Object.<anonymous> (/tmp/node-npm-5iGk/bin/npm-cli.js:77:3)
           at Module._compile (module.js:449:26)
           at Object.Module._extensions..js (module.js:467:10)
           at Module.load (module.js:356:32)
           at Function.Module._load (module.js:312:12)
           at Module.require (module.js:362:17)
           at require (module.js:378:17)
           at Object.<anonymous> (/tmp/node-npm-5iGk/cli.js:2:1)
           at Module._compile (module.js:449:26)
       Dependencies installed
-----> Discovering process types
       Procfile declares types -> mongod, redis, web
-----> Compiled slug size is 5.0MB
-----> Launching... done, v9

Запуск "Heroku PS" подтверждает падение. Хорошо, нет проблем, поэтому я откатил изменения, добавил node_module обратно в репозиторий git и удалил его из .gitignore. Тем не менее, даже после возврата я получаю то же сообщение об ошибке при развертывании, но теперь приложение снова работает правильно. Запуск "heroku PS" говорит мне, что приложение работает.

Итак, мой вопрос, как правильно это сделать? Включить node_modules или нет? И почему я все еще получаю сообщение об ошибке при откате? Я думаю, что хранилище git находится в плохом состоянии на стороне Heroku?

Джейсон Гриффин
источник
10
Я владелец языка Node в Heroku, и ответ прост: Нет. Не node_modulesрегистрируйтесь в приложениях Heroku.
hunterloftis
@hunterloftis 'Не регистрировать node_modules в ' или 'Не регистрировать node_modules в '? Чтобы уточнить, как владелец языка Node в Heroku, вы хотите, чтобы мы загружали все наши node_modules через наш git push или нет? Я предпочитаю этого не делать из-за потери пропускной способности и того факта, что Heroku получит их на бэкэнд моего git push; однако мне пришлось редактировать файлы в моих node_modules вручную, чтобы Heroku загрузил мое приложение. Поэтому мне пришлось игнорировать node_modules за вычетом всего модуля, который включал мой отредактированный файл, чтобы заставить его работать.
ZStoneDPM

Ответы:

400

Второе обновление

FAQ больше не доступен.

Из документации shrinkwrap:

Если вы хотите заблокировать определенные байты, включенные в пакет, например, чтобы иметь 100% уверенность в том, что сможете воспроизвести развертывание или сборку, то вам следует проверить свои зависимости в управлении исходным кодом или использовать какой-то другой механизм, который может проверить содержание, а не версии.

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


Обновить

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

Обычно нет. Разрешите npm разрешать зависимости для ваших пакетов.

Для развертываемых пакетов, таких как веб-сайты и приложения, вы должны использовать npm shrinkwrap, чтобы заблокировать полное дерево зависимостей:

https://docs.npmjs.com/cli/shrinkwrap


Оригинальный пост

Для справки, npm FAQ четко отвечает на ваш вопрос:

Проверьте node_modules в git для вещей, которые вы развертываете, таких как веб-сайты и приложения. Не проверяйте node_modules в git для библиотек и модулей, предназначенных для повторного использования. Используйте npm для управления зависимостями в вашей среде разработки, но не в сценариях развертывания.

и для некоторого хорошего обоснования этого прочитайте пост Mikeal Rogers об этом .


Источник: https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git

Kostia
источник
13
Это не правильно - на самом деле это очень плохая идея. Если вы разрабатываете для Windows, а затем развертываете в Linux, вам потребуется перестроить node_modules при развертывании. Что значит - хаос. Много модифицированных файлов, и не знаю, что делать.
user3690202
8
Это невозможно - некоторые наши разработчики разрабатывают целевые окна, другие - Linux, но имеют ту же базу кода. Наилучшим подходом было бы не фиксировать узлы модулей - упс.
user3690202
7
@ user3690202 Звучит так, как будто у вас очень необычный случай, а не норма, поэтому высказывание «это неправильно», вероятно, является преувеличением. Сказав это, я не знаю точно, каков ваш конкретный вариант использования, но я не могу придумать ни одной причины для использования как windows, так и linux для разработки. Придерживайтесь одного и запускайте тесты или QA на всех платформах вашей поддержки.
Костя
16
@ Kostia Наш пример использования довольно распространен. Мы волонтеры и используем собственные машины, а не компании. Похоже, довольно распространенная ситуация для открытого исходного кода.
Адам
4
@ Adam тангенциально, не могли бы вы добавить компилируемые файлы .gitignore? Таким образом, исходный код находится в git, а любые скомпилированные компоненты - нет, аналогично тому, как distили outputgitignored папки в проектах grunt и gulp.
Костя
160

Моя самая большая проблема с тем, чтобы не проверять node_modulesgit, - это то, что через 10 лет, когда ваше производственное приложение все еще используется, npm может не появиться. Или npm может быть поврежден; или сопровождающие могут решить удалить библиотеку, на которую вы полагаетесь, из своего хранилища; или версия, которую вы используете, может быть урезана.

Это можно смягчить с помощью менеджеров репо, таких как maven, потому что вы всегда можете использовать свой собственный локальный Nexus или Artifactory для поддержки зеркала с пакетами, которые вы используете. Насколько я понимаю, такой системы не существует для npm. То же самое касается менеджеров библиотек на стороне клиента, таких как Bower и Jamjs.

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

Джонатан
источник
10
Сегодня доступно множество вариантов: Nexus ( Issues.sonatype.org/browse/NEXUS-5852 ), Artifactory ( jfrog.com/jira/browse/RTFACT-5143 ), npm_lazy ( github.com/mixu/npm_lazy ), npm-lazy- зеркало ( npmjs.org/package/npm-lazy-mirror ) и т. д.
Иоганн
4
Цитата из часто задаваемых вопросов по npmjs: «Если вы не уверены в зависимости от экосистемы npm, вы должны запустить личное зеркало npm или личный кеш». Я думаю, что это указывает на проблему, о которой вы говорите, верно?
Тайлан
3
Показательный пример developers.slashdot.org/story/16/03/23/0652204/…
прототип
2
Npm не исчезнет за ночь, поэтому выгода не очень хорошо сочетается с потерей ясности в истории ваших коммитов и огромного размера пакета. Если кто-то создает приложение, которое, по его мнению, будет активным в течение 10 лет, разумно ожидать, что оно получит много поддержки в процессе работы. Тем не менее, аргумент о сбоях в работе NPM является гораздо лучшим аргументом, хотя, возможно, существуют более эффективные способы снижения этого риска, чем принятие источника.
Сэм П
3
Даже один месяц в будущем опасен, если вы не фиксируете свои зависимости (желательно в отдельном репозитории). Как я обнаружил однажды утром, когда я клонировал один из моих проектов и обнаружил, что версия пакета была удалена из npm. Я потратил полдня на изменение всех моих версий каскадных зависимостей, чтобы заставить работать обновление npm и строить снова.
Ричард
67

Вы не должны включатьnode_modules в свой .gitignore(или, скорее, вы должны включить node_modules в свой источник, развернутый в Heroku).

Если node_modules:

  • Существуют, затем npm installбудут использовать эти библиотеки и будут перестраивать любые бинарные зависимости npm rebuild.
  • не существует, то npm installпридется самому извлекать все зависимости, что добавляет время к этапу компиляции слагов.

Посмотрите исходный код Node.js buildpack для этих точных шагов

Однако первоначальная ошибка выглядит несовместимой между версиями npmи node. Рекомендуется всегда явно указывать свой enginesраздел в packages.jsonсоответствии с данным руководством, чтобы избежать следующих ситуаций:

{
  "name": "myapp",
  "version": "0.0.1",
  "engines": {
    "node": "0.8.x",
    "npm":  "1.1.x"
  }
}

Это обеспечит равенство между разработчиками и снизит вероятность возникновения подобных ситуаций в будущем.

Райан Дейгл
источник
Спасибо за помощь Райан. Это помогло мне избежать ошибки версии npm, но теперь она не работает при компиляции пакета redis. Сообщение об ошибке: «OSError: [Errno 2] Нет такого файла или каталога: '/ Users / Jason / tastemade / tastebase / node_modules / redis-url / node_modules / redis / node_modules / hiredis / build'». Похоже, он использует путь из моего локального ящика на серверах heroku. Есть ли определенные файлы в node_modules, которые мне нужно добавить в .gitignore?
Джейсон Гриффин
Я не уверен, что происходит с этой конкретной библиотекой, но я бы попробовал исключить node_modules из git в этом случае и посмотреть, поможет ли это (принудительно заставляя npm извлекать все самому и обеспечивая новую среду сборки).
Райан Дейгл
@RyanDaigle Лучшая практика (ноябрь 2013), рекомендованная как npm ( npmjs.org/doc/… ), так и heroku ( devcenter.heroku.com/articles/… ), состоит в том, чтобы проверять наличие в node_modules для git. Обновите ли вы свой ответ (так как он имеет самый высокий счет)?
Тим Диггинс
При нажатии на heroku вы получите вывод «-----> Caching node_modules каталог для будущих сборок». Это должно сократить будущую компиляцию пули.
ph3nx
У меня проблема в том, что путь к файлу node_modules слишком длинный для фиксации. Git не найдет файлы.
Код фараона
22

Я собирался оставить это после этого комментария: Должен ли я включить node_modules для git при создании приложения node.js на Heroku?

Но stackoverflow форматировал это странно. Если у вас нет идентичных машин и вы проверяете в node_modules, сделайте .gitignore для собственных расширений. Наш .gitignore выглядит так:

# Ignore native extensions in the node_modules folder (things changed by npm rebuild)
node_modules/**/*.node
node_modules/**/*.o
node_modules/**/*.a
node_modules/**/*.mk
node_modules/**/*.gypi
node_modules/**/*.target
node_modules/**/.deps/
node_modules/**/build/Makefile
node_modules/**/**/build/Makefile

Проверьте это, сначала проверив все, а затем попросите другого разработчика сделать следующее:

rm -rf node_modules
git checkout -- node_modules
npm rebuild
git status

Убедитесь, что файлы не изменены.

ibash
источник
Просто добавил это. Решил мою проблему. Windows github продолжал падать, пытаясь перебрать 7000+ файлов node_module: /
Batman
10

Я считаю, что npm installне должен работать в производственной среде. Есть несколько вещей, которые могут пойти не так - сбой npm, загрузка новых зависимостей (shrinkwrap, похоже, решил эту проблему) - две из них.

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

Наилучшие решения будут такими: они npm installдолжны работать в среде CI, аналогичной производственной среде. Все тесты будут выполнены, и будет создан заархивированный файл выпуска, который будет включать все зависимости.

user2468170
источник
Почему у вас есть шаг, который выполняется на CI, который не будет выполняться как часть вашего развертывания? Это означает, что у вас нет паритета между двумя системами! Как сказано в ответе выше - коммит папки просто игнорирует собственные расширения, таким образом, вы покрыты такими вещами, как
сбои в работе
1
Спасибо за ваш комментарий. Я считаю, что node_modules, которые запускаются на вашем производственном сервере, должны быть сгенерированы из установки npm, а не из того, что разработчики сделали. Папка dev_modules разработчика не обязательно соответствует содержимому package.json.
user2468170
8

Я использовал как фиксацию в папке node_modules, так и упаковку в термоусадочную пленку. Оба решения не сделали меня счастливым.

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

Я обнаружил, что Mozilla использует отдельный репозиторий для одного из своих проектов https://github.com/mozilla-b2g/gaia-node-modules

Поэтому мне не потребовалось много времени, чтобы реализовать эту идею в инструменте CLI узла https://github.com/bestander/npm-git-lock

Непосредственно перед каждой сборкой добавляйте
npm-git-lock --repo [git@bitbucket.org: ваши / выделенные / node_modules / git / repository.git]

Он вычислит хеш вашего package.json и либо извлечет содержимое node_modules из удаленного репо, либо, если это первая сборка для этого package.json, выполнит очистку npm installи отправит результаты в удаленное репо.

bestander
источник
5

Для меня сработало явное добавление версии npm в package.json («npm»: «1.1.x») и НЕ проверка в node_modules для git. Это может быть медленнее для развертывания (так как он загружает пакеты каждый раз), но я не смог заставить пакеты скомпилировать, когда они были возвращены. Heroku искал файлы, которые существовали только в моем локальном ящике.

Джейсон Гриффин
источник
Если вы считаете, что мой ответ был правильным, пожалуйста, примите его? Спасибо!
Райан Дейгл
В случае, если это все еще подлежит обсуждению, я бы посмотрел на этот пост stackoverflow, который является почти дубликатом вашего вопроса выше: stackoverflow.com/questions/11459733/… По сути, кажется, что соглашение состоит в том, чтобы проверить в node_modules, и управлять вашими версиями этих модулей локально. Это кажется довольно разумным, и, возможно, самое краткое объяснение таково: mikealrogers.com/posts/nodemodules-in-git.html Удачи!
воин
3

Вместо проверки в node_modules, создайте файл package.json для своего приложения.

Файл package.json определяет зависимости вашего приложения. Затем Heroku может указать npm установить все эти зависимости. Учебник, на который вы ссылаетесь, содержит раздел о файлах package.json.

matzahboy
источник
У меня есть package.json. Он имеет следующее: {"name": "node-example", "version": "0.0.1", "dependencies": {"express": "2.5.x", "redis-url": "0.1. 0 "," mongodb ":"> = 0.9.9 "}," engine ": {" node ":" 0.8.x "}}
Джейсон Гриффин
Я сделал в своем локальном окне, чтобы создать каталог node_modules. Это то, что я зарегистрировал, затем удалил, затем добавил обратно.
Джейсон Гриффин
После более подробного изучения учебника кажется, что они фиксируют node_modules. В этом случае я не уверен, есть ли способ не фиксировать node_modules. Извините
Мацбойбой
3

Я использую это решение:

  1. Создайте отдельный репозиторий, который содержит node_modules. Если у вас есть собственные модули, которые должны быть собраны для конкретной платформы, создайте отдельный репозиторий для каждой платформы.
  2. Присоедините эти репозитории к вашему репозиторию проекта с помощью git submodule:

git submodule add .../your_project_node_modules_windows.git node_modules_windows

git submodule add .../your_project_node_modules_linux_x86_64 node_modules_linux_x86_64

  1. Создайте ссылку с конкретной платформы node_modulesна node_modulesкаталог и добавьте node_modulesв .gitignore.
  2. Беги npm install.
  3. Зафиксируйте изменения в хранилище субмодуля.
  4. Зафиксируйте ваш репозиторий проекта.

Таким образом, вы можете легко переключаться между node_modulesразличными платформами (например, если вы разрабатываете на OS X и развертываете на Linux).

Mixel
источник
3

С https://web.archive.org/web/20150212165006/http://www.futurealoof.com/posts/nodemodules-in-git.html :

Изменить: Первоначальная ссылка была этой, но теперь она мертва. Спасибо @Flavio за то, что указал на это.

Напомним.

  • Только проверяйте node_modules для приложений, которые вы развертываете, а не для повторного использования пакетов, которые вы поддерживаете.
  • Любые скомпилированные зависимости должны иметь свой исходный код, а не цели компиляции, и должны $ npm перестраиваться при развертывании.

Моя любимая часть:

Все вы, люди, которые добавили node_modules в ваш gitignore, удалите это дерьмо, сегодня это артефакт эпохи, которую мы слишком рады оставить позади. Эра глобальных модулей мертва.

Бенджамин Крузье
источник
Похоже, что сайт, на который вы ссылались, истек и теперь полон мошеннической рекламы. Я хотел бы, чтобы эти объявления были "артефактами эпохи, которую мы все были бы слишком счастливы оставить позади".
Флавио Копес
1
@FlavioCopes Обновил мой ответ со ссылкой с Wayback Machine.
Бенджамин Крузье
2

http://nodejs.org/api/modules.html

[...] узел начинается в родительском каталоге текущего модуля, добавляет /node_modulesи пытается загрузить модуль из этого расположения.

Если он там не найден, он перемещается в родительский каталог и так далее , пока не будет достигнут корень дерева.

Если вы катите свои собственные модули, специфичные для вашего приложения, вы можете оставить эти ( и только те ) в своем приложении /node_modules. И переместить все остальные зависимости в родительский каталог.

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

laggingreflex
источник
1

сценарий 1:

Один сценарий: вы используете пакет, который удаляется из npm. Если у вас есть все модули в папке node_modules, то это не будет проблемой для вас. Если у вас есть только имя пакета в package.json, вы больше не сможете его получить. Если пакету менее 24 часов, вы можете легко удалить его из npm. Если возраст старше 24 часов, вам необходимо связаться с ними. Но:

Если вы обратитесь в службу поддержки, они проверит, не нарушит ли удаление этой версии вашего пакета какие-либо другие установки. Если это так, мы не будем удалять его.

читать далее

Так что шансы на это невелики, но есть сценарий 2 ...


сценарий 2:

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

"dependencies": {
    "studpid-package": "~1.0.1"
}

Вы используете метод function1(x)этого пакета.

Теперь разработчики studpid-package переименовывают метод function1(x)в, function2(x)и они делают ошибку ... Они изменяют версию своего пакета с 1.0.1на 1.1.0. Это проблема, потому что при npm installследующем вызове вы примете версию, 1.1.0потому что вы использовали тильду ( "studpid-package": "~1.0.1").

Вызов function1(x)может вызвать ошибки и проблемы сейчас.


Перенос всей папки node_modules (часто более 100 МБ) в ваш репозиторий обойдется вам в пространство памяти. Несколько килобайт (только package.json) по сравнению с сотнями МБ (package.json & node_modules) ... Подумайте об этом.

Вы можете сделать это / должны подумать об этом, если:

  • программное обеспечение очень важно.

  • это стоит ваших денег, когда что-то не получается.

  • Вы не доверяете реестру npm. npm централизован и теоретически может быть отключен.

Вам не нужно публиковать папку node_modules в 99,9% случаев, если:

  • Вы разрабатываете программное обеспечение только для себя.

  • Вы что-то запрограммировали и просто хотите опубликовать результат на GitHub, потому что это может заинтересовать кого-то другого.


Если вы не хотите, чтобы node_modules присутствовали в вашем хранилище, просто создайте .gitignoreфайл и добавьте строку node_modules.

ndsvw
источник