Dois-je archiver node_modules pour git lors de la création d'une application node.js sur Heroku?


368

J'ai suivi les instructions de démarrage de base pour node.js sur Heroku ici:

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

Ces instructions ne vous disent pas de créer un .gitignore node_modules, et impliquent donc que node_modules doit être archivé pour git. Lorsque j'inclus node_modules dans git, mon application de démarrage s'est correctement déroulée.

Quand j'ai suivi l'exemple le plus avancé sur:

https://devcenter.heroku.com/articles/realtime-polyglot-app-node-ruby-mongodb-socketio https://github.com/mongolab/tractorpush-server (source)

Il m'a demandé d'ajouter node_modules à .gitignore. J'ai donc supprimé node_modules de git, l'ai ajouté à .gitignore, puis redéployé. Cette fois, le déploiement a échoué comme suit:

-----> 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

L'exécution de "heroku ps" confirme le crash. Ok, pas de problème, j'ai donc annulé la modification, ajouté node_module au référentiel git et supprimé de .gitignore. Cependant, même après le rétablissement, je reçois toujours le même message d'erreur lors du déploiement, mais maintenant l'application fonctionne à nouveau correctement. L'exécution de "heroku ps" m'indique que l'application est en cours d'exécution.

Donc ma question est quelle est la bonne façon de procéder? Inclure noeud_modules ou non? Et pourquoi recevrais-je toujours le message d'erreur lors de la restauration? Je suppose que le dépôt git est en mauvais état du côté Heroku?


10
Je suis propriétaire de la langue du nœud chez Heroku et la réponse est simple: non. Ne vous connectez pas node_modulesaux applications Heroku.
hunterloftis

@hunterloftis 'Ne pas archiver node_modules dans ' ou 'Ne pas archiver node_modules dans '? Pour clarifier, en tant que propriétaire de la langue du nœud chez Heroku, voulez-vous que nous téléchargions tous nos node_modules via notre git push ou non? Je préfère ne pas le faire en raison du gaspillage de bande passante et du fait que Heroku les mettra en arrière-plan de mon git push; cependant, j'ai dû modifier manuellement des fichiers dans mes node_modules pour que Heroku charge mon application. J'ai donc dû ignorer node_modules moins tout le module qui comprenait mon fichier édité pour le faire fonctionner.
ZStoneDPM

Réponses:


400

Deuxième mise à jour

La FAQ n'est plus disponible.

À partir de la documentation de shrinkwrap:

Si vous souhaitez verrouiller les octets spécifiques inclus dans un package, par exemple pour être sûr à 100% de pouvoir reproduire un déploiement ou une génération, vous devez vérifier vos dépendances dans le contrôle de code source, ou poursuivre un autre mécanisme qui peut vérifier contenu plutôt que des versions.

Shannon et Steven l'ont déjà mentionné, mais je pense que cela devrait faire partie de la réponse acceptée.


Mise à jour

La source répertoriée pour la recommandation ci-dessous a été mise à jour . Ils ne recommandent plus que le node_modulesdossier soit validé.

Habituellement, non. Autorisez npm à résoudre les dépendances de vos packages.

Pour les packages que vous déployez, tels que les sites Web et les applications, vous devez utiliser npm shrinkwrap pour verrouiller votre arbre de dépendance complet:

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


Message d'origine

Pour référence, la FAQ npm répond clairement à votre question:

Vérifiez node_modules dans git pour les éléments que vous déployez, tels que les sites Web et les applications. Ne pas archiver node_modules dans git pour les bibliothèques et modules destinés à être réutilisés. Utilisez npm pour gérer les dépendances dans votre environnement de développement, mais pas dans vos scripts de déploiement.

et pour une bonne raison à cela, lisez le post de Mikeal Rogers à ce sujet .


Source: https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git


13
Ce n'est pas correct - en fait, c'est une très mauvaise idée. Si vous développez sur Windows puis déployez sur Linux, vous devrez reconstruire node_modules lors de votre déploiement. Ce qui signifie - le chaos. Beaucoup de fichiers modifiés, et aucune idée de quoi faire.
user3690202

8
Ce n'est pas possible - certains de nos développeurs développent des fenêtres de ciblage, d'autres ciblent linux, mais la même base de code. La meilleure approche serait de ne pas valider les modules de nœuds - oups.
user3690202

7
@ user3690202 On dirait que vous avez un cas très peu conventionnel, plutôt que la norme, donc dire "ce n'est pas correct" est probablement une surestimation. Cela dit, je ne sais pas quel est votre cas d'utilisation exact, mais je ne vois aucune raison d'utiliser Windows et Linux pour le développement. Tenez-vous-en à un et exécutez des tests ou un contrôle qualité sur toutes les plates-formes de votre support.
Kostia

16
@Kostia Notre cas d'utilisation est assez courant. Nous sommes bénévoles et utilisons nos propres machines, pas celles de l'entreprise. On dirait une situation assez courante pour l'open source.
Adam

4
@Adam tangentiellement, pourriez-vous ajouter les fichiers en cours de compilation .gitignore? De cette façon, la source est dans git, et tous les composants compilés ne le sont pas, de la même manière que les dossiers distou outputsont gitignored dans les projets grunt et gulp.
Kostia

160

Ma plus grande préoccupation de ne pas vérifier node_modulesdans git est que 10 ans plus tard, lorsque votre application de production est toujours en cours d'utilisation, npm peut ne pas être là. Ou npm pourrait être corrompu; ou les responsables peuvent décider de supprimer la bibliothèque sur laquelle vous comptez de leur référentiel; ou la version que vous utilisez peut être supprimée.

Cela peut être atténué avec des gestionnaires de référentiels comme maven, car vous pouvez toujours utiliser votre propre Nexus ou Artifactory local pour maintenir un miroir avec les packages que vous utilisez. Autant que je sache, un tel système n'existe pas pour npm. Il en va de même pour les gestionnaires de bibliothèques côté client comme Bower et Jamjs.

Si vous avez validé les fichiers dans votre propre dépôt git, vous pouvez les mettre à jour quand vous le souhaitez, et vous avez le confort de builds répétables et la connaissance que votre application ne se cassera pas en raison d'une action tierce.


10
De nombreuses options aujourd'hui: Nexus ( issues.sonatype.org/browse/NEXUS-5852 ), Artifactory ( jfrog.com/jira/browse/RTFACT-5143 ), npm_lazy ( github.com/mixu/npm_lazy ), npm-lazy- miroir ( npmjs.org/package/npm-lazy-mirror ), etc.
Johann

4
Citation de la FAQ npmjs: "Si vous êtes paranoïaque en fonction de l'écosystème npm, vous devez exécuter un miroir npm privé ou un cache privé.". Je pense que cela pointe vers le problème auquel vous faites référence, non?
Taylan


2
Npm ne disparaîtra pas pendant la nuit, donc l'avantage ne se marie pas vraiment avec la perte de clarté de votre historique de commit et de la taille énorme de votre bundle. Si quelqu'un crée une application qui, selon lui, sera toujours active dans 10 ans, il est raisonnable de s'attendre à ce qu'elle reçoive beaucoup de maintenance en cours de route. Le point sur les pannes du NPM est un bien meilleur argument, bien qu'il existe probablement de meilleures façons d'atténuer ce risque que de s'engager à la source.
Sam P

3
Même un mois plus tard est dangereux si vous ne validez pas vos dépendances (de préférence dans un référentiel séparé). Comme je l'ai trouvé un matin, lorsque j'ai cloné un de mes projets, j'ai découvert qu'une version de package avait été supprimée de npm. J'ai passé une demi-journée à changer toutes mes versions de dépendances en cascade pour que la mise à jour npm fonctionne et se reconstruise.
Richard

67

Vous ne devez pas inclure node_modules dans votre .gitignore(ou plutôt vous devez inclure node_modules dans votre source déployée sur Heroku).

Si node_modules:

  • existe alors npm installutilisera ces bibliothèques vendues et reconstruira toutes les dépendances binaires avec npm rebuild.
  • n'existe pas alors npm installdevra récupérer toutes les dépendances lui-même, ce qui ajoute du temps à l'étape de compilation de slug.

Voir la source du buildpack Node.js pour ces étapes exactes

Cependant, l'erreur d'origine semble être une incompatibilité entre les versions de npmet node. C'est une bonne idée de toujours définir explicitement la enginessection de votre packages.jsonselon ce guide pour éviter ces types de situations:

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

Cela garantira la parité dev / prod et réduira la probabilité de telles situations à l'avenir.


Merci pour l'aide Ryan. Cela m'a permis de dépasser l'erreur de version npm mais maintenant elle échoue lors de la compilation du package redis. Le message d'erreur est "OSError: [Errno 2] Aucun fichier ou répertoire de ce type: '/ Users / Jason / tastemade / tastbase / node_modules / redis-url / node_modules / redis / node_modules / hiredis / build'". Il semble qu'il utilise un chemin d'accès depuis ma boîte locale sur les serveurs Heroku. Y a-t-il certains fichiers dans le node_modules que je dois ajouter à .gitignore?
Jason Griffin

Je ne sais pas ce qui se passe avec cette bibliothèque particulière, mais j'essaierais d'exclure node_modules de git dans ce cas et de voir si cela aide (forçant npm à tout récupérer lui-même et à assurer un nouvel environnement de construction).
Ryan Daigle

@RyanDaigle La meilleure pratique maintenant (novembre 2013) recommandée par npm ( npmjs.org/doc/… ) et heroku ( devcenter.heroku.com/articles/… ) consiste à archiver node_modules pour git. Souhaitez-vous mettre à jour votre réponse (car elle a la facturation la plus élevée)?
Tim Diggins

En poussant vers heroku, vous obtiendrez la sortie "-----> Mise en cache du répertoire node_modules pour les futures générations". C'est pour raccourcir la future compilation de slug.
ph3nx

J'ai un problème que le chemin du fichier node_modules est trop long pour être validé. Git ne trouvera pas les fichiers.
Code Pharaoh du

22

J'allais laisser cela après ce commentaire: Dois-je enregistrer node_modules pour git lors de la création d'une application node.js sur Heroku?

Mais stackoverflow le formait bizarrement. Si vous n'avez pas de machines identiques et que vous archivez node_modules, faites un .gitignore sur les extensions natives. Notre .gitignore ressemble à:

# 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

Testez cela en vérifiant d'abord tout, puis demandez à un autre développeur d'effectuer les opérations suivantes:

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

Assurez-vous qu'aucun fichier n'a été modifié.


Je viens de l'ajouter. Résolu mon problème. Le github de Windows a continué de planter en essayant de parcourir plus de 7000 fichiers node_module: /
Batman

10

Je crois que cela npm installne devrait pas fonctionner dans un environnement de production. Il y a plusieurs choses qui peuvent mal tourner - panne de npm, téléchargement de dépendances plus récentes (le shrinkwrap semble avoir résolu ce problème) en sont deux.

En revanche, node_modulesne doit pas être engagé sur git. En dehors de leur grande taille, les commits les incluant peuvent devenir distrayants.

La meilleure solution serait la suivante: npm installdevrait s'exécuter dans un environnement CI similaire à l'environnement de production. Tous les tests seront exécutés et un fichier de version compressé sera créé qui inclura toutes les dépendances.


Pourquoi avez-vous une étape qui s'exécute sur CI qui ne s'exécuterait pas dans le cadre de votre déploiement? Cela signifie que vous n'avez pas de parité entre les 2 systèmes! Comme la réponse le dit ci-dessus - validez le dossier en ignorant simplement les extensions natives, de cette façon vous êtes couvert pour des choses comme les pannes npm
Voycey

1
Merci pour votre commentaire. Je crois que les node_modules qui s'exécutent sur votre serveur de production devraient être générés à partir d'une installation npm, et non à partir de ce que les développeurs ont commis. Le dossier node_modules d'un développeur ne correspond pas nécessairement au contenu package.json.
user2468170

8

J'utilise à la fois la validation du dossier node_modules et le rétrécissement. Les deux solutions ne m'ont pas fait plaisir.

En bref: les node_modules validés ajoutent trop de bruit au référentiel.
Et shrinkwrap.json n'est pas facile à gérer et il n'y a aucune garantie qu'un projet sous film rétractable se construira dans quelques années.

J'ai trouvé que Mozilla utilisait un référentiel séparé pour l'un de leurs projets https://github.com/mozilla-b2g/gaia-node-modules

Il ne m'a donc pas fallu longtemps pour implémenter cette idée dans un outil CLI de nœud https://github.com/bestander/npm-git-lock

Juste avant chaque build, ajoutez
npm-git-lock --repo [git@bitbucket.org: votre / dédié / node_modules / git / repository.git]

Il calculera le hachage de votre package.json et vérifiera le contenu node_modules d'un référentiel distant, ou, s'il s'agit d'une première version de ce package.json, effectuera un nettoyage npm installet enverra les résultats au référentiel distant.


5

Ce qui a fonctionné pour moi a été d'ajouter explicitement une version npm à package.json ("npm": "1.1.x") et de NE PAS archiver node_modules dans git. Il peut être plus lent à déployer (car il télécharge les packages à chaque fois), mais je n'ai pas pu compiler les packages lorsqu'ils ont été enregistrés. Heroku recherchait des fichiers qui n'existaient que sur ma boîte locale.


Si vous pensez que ma réponse était la bonne, veuillez l'accepter? Je vous remercie!
Ryan Daigle

Dans le cas où cela serait encore à débattre, je voudrais jeter un œil à ce post stackoverflow qui est presque un double de votre question ci-dessus: stackoverflow.com/questions/11459733/… Fondamentalement, il semble que la convention consiste à archiver node_modules, et gérer vos versions de ces modules localement. Cela semble assez raisonnable, et l'explication peut-être la plus succincte est la suivante: mikealrogers.com/posts/nodemodules-in-git.html Bonne chance!
warriorpostman

3

Au lieu d'archiver node_modules, créez un fichier package.json pour votre application.

Le fichier package.json spécifie les dépendances de votre application. Heroku peut alors demander à npm d'installer toutes ces dépendances. Le didacticiel auquel vous avez lié contient une section sur les fichiers package.json.


J'ai un package.json. Il a les éléments suivants: {"nom": "exemple-nœud", "version": "0.0.1", "dépendances": {"express": "2.5.x", "redis-url": "0.1. 0 "," mongodb ":"> = 0.9.9 "}," moteurs ": {" node ":" 0.8.x "}}
Jason Griffin

J'ai fait sur ma boîte locale pour créer le répertoire node_modules. C'est ce que j'ai vérifié, puis supprimé, puis ajouté.
Jason Griffin

Après avoir regardé le tutoriel plus, il semble qu'ils commettent node_modules. Dans ce cas, je ne sais pas s'il existe un moyen de ne pas valider node_modules. Désolé
matzahboy

3

J'utilise cette solution:

  1. Créez un référentiel distinct qui contient node_modules. Si vous avez des modules natifs qui doivent être créés pour une plate-forme spécifique, créez un référentiel distinct pour chaque plate-forme.
  2. Attachez ces référentiels à votre référentiel de projet avec 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. Créez un lien de la plate-forme node_modulesvers le node_modulesrépertoire et ajoutez- node_modulesle .gitignore.
  2. Courez npm install.
  3. Validez les modifications du référentiel de sous-module.
  4. Validez les modifications du référentiel de votre projet.

Vous pouvez donc facilement basculer entre node_modulessur différentes plates-formes (par exemple si vous développez sur OS X et déployez sur Linux).


3

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

Edit: Le lien d'origine était celui-ci mais il est maintenant mort. Merci @Flavio de l'avoir signalé.

Récapituler.

  • Archivez uniquement node_modules pour les applications que vous déployez, pas les packages réutilisables que vous gérez.
  • Toutes les dépendances compilées doivent avoir leur source archivée, pas les cibles de compilation, et doivent reconstruire $ npm lors du déploiement.

Ma partie préférée:

Vous tous qui avez ajouté node_modules à votre gitignore, supprimez cette merde, aujourd'hui , c'est un artefact d'une époque que nous sommes trop heureux de laisser derrière. L'ère des modules mondiaux est morte.


Le site que vous avez lié semble avoir expiré et est maintenant rempli d'annonces frauduleuses. Je souhaite que ces publicités soient "des artefacts d'une époque que nous serions tous trop heureux de laisser derrière nous".
Flavio Copes

1
@FlavioCopes Mise à jour de ma réponse avec le lien de Wayback Machine.
Benjamin Crouzier

2

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

Le nœud [...] commence au répertoire parent du module actuel, ajoute /node_moduleset tente de charger le module à partir de cet emplacement.

S'il n'y est pas trouvé, il se déplace vers le répertoire parent, et ainsi de suite , jusqu'à ce que la racine de l'arborescence soit atteinte.

Si vous déployez vos propres modules spécifiques à votre application, vous pouvez les conserver ( et uniquement ceux ) dans ceux de votre application /node_modules. Et déplacez toutes les autres dépendances vers le répertoire parent.

Ce cas d'utilisation est assez génial, il vous permet de conserver les modules que vous avez créés spécifiquement pour votre application avec votre application, et n'encombre pas votre application avec des dépendances qui peuvent être installées plus tard.


1

Scénario 1:

Un scénario: vous utilisez un package qui est supprimé de npm. Si vous avez tous les modules dans le dossier node_modules, alors ce ne sera pas un problème pour vous. Si vous n'avez que le nom du package dans le package.json, vous ne pouvez plus l'obtenir. Si un colis a moins de 24 heures, vous pouvez facilement le retirer de npm. Si elle date de plus de 24 heures, vous devez les contacter. Mais:

Si vous contactez le support, ils vérifieront si la suppression de cette version de votre package interrompt toute autre installation. Si c'est le cas, nous ne le supprimerons pas.

Lire la suite

Les chances sont donc faibles, mais il y a le scénario 2 ...


scénario 2:

Un autre scénario où c'est le cas: vous développez une version entreprise de votre logiciel ou un logiciel très important et écrivez dans votre package.json:

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

Vous utilisez la méthode function1(x) de ce package.

Maintenant, les développeurs de studpid-package renomment la méthode function1(x)en function2(x)et ils font une erreur ... Ils changent la version de leur package de 1.0.1en 1.1.0. C'est un problème car lorsque vous appellerez npm installla prochaine fois, vous accepterez la version1.1.0 car vous avez utilisé le tilde ( "studpid-package": "~1.0.1").

Appel function1(x) peut provoquer des erreurs et des problèmes maintenant.


Pousser l'intégralité du dossier node_modules (souvent plus de 100 Mo) vers votre référentiel vous coûtera de l'espace mémoire. Quelques ko (package.json uniquement) par rapport à des centaines de Mo (package.json & node_modules) ... Pensez-y.

Vous pourriez le faire / devriez y penser si:

  • le logiciel est très important.

  • cela vous coûte de l'argent quand quelque chose échoue.

  • vous ne faites pas confiance au registre npm. npm est centralisé et pourrait théoriquement être arrêté.

Vous n'avez pas besoin de publier le dossier node_modules dans 99,9% des cas si:

  • vous développez un logiciel juste pour vous.

  • vous avez programmé quelque chose et vous voulez juste publier le résultat sur GitHub parce que quelqu'un d'autre pourrait peut-être s'y intéresser.


Si vous ne voulez pas que les node_modules soient dans votre référentiel, créez simplement un .gitignorefichier et ajoutez la ligne node_modules.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.