问题
I followed the basic getting started instructions for node.js on Heroku here:
https://devcenter.heroku.com/categories/nodejs
These instruction don't tell you to create a .gitignore node_modules, and therefore imply that node_modules should be checked in to git. When I include node_modules in git my getting started application ran correctly.
When I followed the more advanced example at:
https://devcenter.heroku.com/articles/realtime-polyglot-app-node-ruby-mongodb-socketio https://github.com/mongolab/tractorpush-server (source)
It instructed me to add node_modules to .gitignore. So I removed node_modules from git, added it to .gitignore, then re-deployed. This time the deployed failed like so:
-----> 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
Running "heroku ps" confirms the crash. Ok, no problem, so I rolled back the change, add node_module back to the git repository and removed it from .gitignore. However, even after reverting, I still get the same error message on deploy but now the application is running correctly again. Running "heroku ps" tells me the application is running.
So my question is what's the right way to do this? Include node_modules or not? And why would I still be getting the error message when I rollback? My guess is the git repository is in a bad state on the Heroku side?
回答1:
Second Update
The FAQ is not available anymore.
From the documentation of shrinkwrap:
If you wish to lock down the specific bytes included in a package, for example to have 100% confidence in being able to reproduce a deployment or build, then you ought to check your dependencies into source control, or pursue some other mechanism that can verify contents rather than versions.
Shannon and Steven mentioned this before but I think, it should be part of the accepted answer.
Update
The source listed for the below recommendation has been updated. They are no longer recommending the node_modules
folder be committed.
Usually, no. Allow npm to resolve dependencies for your packages.
For packages you deploy, such as websites and apps, you should use npm shrinkwrap to lock down your full dependency tree:
https://docs.npmjs.com/cli/shrinkwrap
Original Post
For reference, npm FAQ answers your question clearly:
Check node_modules into git for things you deploy, such as websites and apps. Do not check node_modules into git for libraries and modules intended to be reused. Use npm to manage dependencies in your dev environment, but not in your deployment scripts.
and for some good rationale for this, read Mikeal Rogers' post on this.
Source: https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
回答2:
My biggest concern with not checking node_modules
into git is that 10 years down the road, when your production application is still in use, npm may not be around. Or npm might become corrupted; or the maintainers might decide to remove the library that you rely on from their repository; or the version you use might be trimmed out.
This can be mitigated with repo managers like maven, because you can always use your own local Nexus or Artifactory to maintain a mirror with the packages that you use. As far as I understand, such a system doesn't exist for npm. The same goes for client-side library managers like Bower and Jamjs.
If you've committed the files to your own git repo, then you can update them when you like, and you have the comfort of repeatable builds and the knowledge that your app won't break because of some third-party action.
回答3:
You should not include node_modules
in your .gitignore
(or rather you should include node_modules in your source deployed to Heroku).
If node_modules
:
- exists then
npm install
will use those vendored libs and will rebuild any binary dependencies withnpm rebuild
. - doesn't exist then
npm install
will have to fetch all dependencies itself which adds time to the slug compile step.
See the Node.js buildpack source for these exact steps
However, the original error looks to be an incompatibility between the versions of npm
and node
. It is a good idea to always explicitly set the engines
section of your packages.json
according to this guide to avoid these types of situations:
{
"name": "myapp",
"version": "0.0.1",
"engines": {
"node": "0.8.x",
"npm": "1.1.x"
}
}
This will ensure dev/prod parity and reduce the likelihood of such situations in the future.
回答4:
I was going to leave this after this comment: Should I check in node_modules to git when creating a node.js app on Heroku?
But stackoverflow was formatting it weird. If you don't have identical machines and are checking in node_modules, do a .gitignore on the native extensions. Our .gitignore looks like:
# 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
Test this by first checking everything in, and then have another dev do the following:
rm -rf node_modules
git checkout -- node_modules
npm rebuild
git status
Ensure that no files changed.
回答5:
I believe that npm install
should not run in a production environment. There are several things that can go wrong - npm outage, download of newer dependencies (shrinkwrap seems to solved this) are two of them.
On the other hand, node_modules
should not be committed on git. Apart from their big size, commits including them can become distracting.
The best solutions would be this: npm install
should run in a CI environment that is similar to the production environment. All tests will run and a zipped release file will be created that will include all dependencies.
回答6:
I have been using both committing node_modules folder and shrink-wrapping. Both solutions did not make me happy.
In short: committed node_modules adds too much noise to repository.
And shrinkwrap.json is not easy to manage and there is no guarantee that some shrink-wrapped project will build in a few years.
I found that Mozilla was using a separate repository for one of their projects https://github.com/mozilla-b2g/gaia-node-modules
So it did not take me long to implement this idea in a node CLI tool https://github.com/bestander/npm-git-lock
Just before every build add
npm-git-lock --repo [git@bitbucket.org:your/dedicated/node_modules/git/repository.git]
It will calculate hash of your package.json and will either check out node_modules content from a remote repo, or, if it is a first build for this package.json, will do a clean npm install
and push the results to the remote repo.
回答7:
What worked for me was explicitly adding a npm version to package.json ("npm": "1.1.x") and NOT checking in node_modules to git. It may be slower to deploy (since it downloads the packages each time), but I couldn't get the packages to compile when they were checked in. Heroku was looking for files that only existed on my local box.
回答8:
Instead of checking in node_modules, make a package.json file for your app.
The package.json file specifies the dependencies of your application. Heroku can then tell npm to install all of those dependencies. The tutorial you linked to contains a section on package.json files.
回答9:
I am using this solution:
- Create separate repository that holds
node_modules
. If you have native modules that should be build for specific platform then create separate repository for each platform. - Attach these repositories to your project repository with
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
- Create link from platform-specific
node_modules
tonode_modules
directory and addnode_modules
to.gitignore
. - Run
npm install
. - Commit submodule repository changes.
- Commit your project repository changes.
So you can easily switch between node_modules
on different platforms (for example if you are developing on OS X and deploying to Linux).
回答10:
From https://web.archive.org/web/20150212165006/http://www.futurealoof.com/posts/nodemodules-in-git.html :
Edit: The original link was this one but it is now dead. Thanks @Flavio for pointing it out.
To recap.
- Only checkin node_modules for applications you deploy, not reusable packages you maintain.
- Any compiled dependencies should have their source checked in, not the compile targets, and should $ npm rebuild on deploy.
My favorite part:
All you people who added node_modules to your gitignore, remove that shit, today, it’s an artifact of an era we’re all too happy to leave behind. The era of global modules is dead.
回答11:
http://nodejs.org/api/modules.html
[...] node starts at the parent directory of the current module, and adds
/node_modules
, and attempts to load the module from that location.If it is not found there, then it moves to the parent directory, and so on, until the root of the tree is reached.
If you're rolling your own modules specific to your app, you can keep those (and only those) in your app's /node_modules
. And move out all the other dependencies to the parent directory.
This use case of pretty awesome, it lets you keep modules you created specifically for your app nicely with your app, and doesn't clutter your app with dependencies which can be installed later.
回答12:
scenario 1:
One scenario: You use a package that gets removed from npm. If you have all the modules in the folder node_modules, then it won't be a problem for you. If you do only have the package name in the package.json, you can't get it anymore. If a package is less than 24 hours old, you can easily remove it from npm. If it's older than 24 hours old, then you need to contact them. But:
If you contact support, they will check to see if removing that version of your package would break any other installs. If so, we will not remove it.
read more
So the chances for this are low, but there is scenario 2...
scenario 2:
An other scenario where this is the case: You develop an enterprise version of your software or a very important software and write in your package.json:
"dependencies": {
"studpid-package": "~1.0.1"
}
You use the method function1(x)
of that package.
Now the developers of studpid-package rename the method function1(x)
to function2(x)
and they make a fault...
They change the version of their package from 1.0.1
to 1.1.0
.
That's a problem because when you call npm install
the next time, you will accept version 1.1.0
because you used the tilde ("studpid-package": "~1.0.1"
).
Calling function1(x)
can cause errors and problems now.
Pushing the whole node_modules folder (often more than 100 MB) to your repository, will cost you memory space. A few kb (package.json only) compared with hundreds of MB (package.json & node_modules)... Think about it.
You could do it / should think about it if:
the software is very important.
it costs you money when something fails.
you don't trust the npm registry. npm is centralized and could theoretically be shut down.
You don't need to publish the node_modules folder in 99.9% of the cases if:
you develop a software just for yourself.
you've programmed something and just want to publish the result on GitHub because someone else could maybe be interested in it.
If you don't want the node_modules to be in your repository, just create a .gitignore
file and add the line node_modules
.
来源:https://stackoverflow.com/questions/11459475/should-i-check-in-node-modules-to-git-when-creating-a-node-js-app-on-heroku