The best way to run npm install for nested folders?
I prefer using post-install, if you know the names of the nested subdir. In package.json
:
"scripts": {
"postinstall": "cd nested_dir && npm install",
...
}
Per @Scott's answer, the install|postinstall script is the simplest way as long as sub-directory names are known. This is how I run it for multiple sub dirs. For example, pretend we have api/
, web/
and shared/
sub-projects in a monorepo root:
// In monorepo root package.json
{
...
"scripts": {
"postinstall": "(cd api && npm install); (cd web && npm install); (cd shared && npm install)"
},
}
Use Case 1: If you want be able to run npm commands from within each subdirectory (where each package.json is), you will need to use postinstall
.
As I often use npm-run-all
anyway, I use it to keep it nice and short (the part in the postinstall):
{
"install:demo": "cd projects/demo && npm install",
"install:design": "cd projects/design && npm install",
"install:utils": "cd projects/utils && npm install",
"postinstall": "run-p install:*"
}
This has the added benefit that I can install all at once, or individually. If you don't need this or don't want npm-run-all
as a dependency, check out demisx's answer (using subshells in postinstall).
Use Case 2: If you will be running all npm commands from the root directory (and, for example, won't be using npm scripts in subdirectories), you could simply install each subdirectory like you would any dependecy:
npm install path/to/any/directory/with/a/package-json
In the latter case, don't be surprised that you don't find any node_modules
or package-lock.json
file in the sub-directories - all packages will be installed in the root node_modules
, which is why you won't be able to run your npm commands (that require dependencies) from any of your subdirectories.
If you're not sure, use case 1 always works.
If you want to run a single command to install npm packages in nested subfolders, you can run a script via npm
and main package.json
in your root directory. The script will visit every subdirectory and run npm install
.
Below is a .js
script that will achieve the desired result:
var fs = require('fs');
var resolve = require('path').resolve;
var join = require('path').join;
var cp = require('child_process');
var os = require('os');
// get library path
var lib = resolve(__dirname, '../lib/');
fs.readdirSync(lib).forEach(function(mod) {
var modPath = join(lib, mod);
// ensure path has package.json
if (!fs.existsSync(join(modPath, 'package.json'))) {
return;
}
// npm binary based on OS
var npmCmd = os.platform().startsWith('win') ? 'npm.cmd' : 'npm';
// install folder
cp.spawn(npmCmd, ['i'], {
env: process.env,
cwd: modPath,
stdio: 'inherit'
});
})
Note that this is an example taken from a StrongLoop article that specifically addresses a modular node.js
project structure (including nested components and package.json
files).
As suggested, you could also achieve the same thing with a bash script.
EDIT: Made the code work in Windows