From 9e28ca4d3860044c962f91ac24039b9b1b795719 Mon Sep 17 00:00:00 2001 From: isaacs Date: Sat, 30 Apr 2011 17:54:45 -0700 Subject: make 'npm help folders' not be a lying liar. --- doc/folders.md | 80 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/doc/folders.md b/doc/folders.md index a36f79653..27f2ec83c 100644 --- a/doc/folders.md +++ b/doc/folders.md @@ -7,6 +7,13 @@ npm puts various things on your computer. That's its job. This document will tell you what it puts where. +### tl;dr + +* Local install (default): puts stuff in ./node_modules +* Global install (with `-g`): puts stuff in /usr/local +* Install it **locally** if you're going to `require()` it. +* Install it **globally** if you're going to run it on the command line. + ### prefix Configuration The `prefix` config defaults to node's `process.installPrefix`. On most @@ -21,11 +28,9 @@ current working directory if not in a package already. Packages are dropped into the `node_modules` folder under the `prefix`. When installing locally, this means that you can `require("packagename")` to load its main module, or -`require("packagename/path/to/sub/module")` to load other modules. +`require("packagename/lib/path/to/sub/module")` to load other modules. -If you wish to install node modules globally which can be loaded via -`require()` from anywhere, then add the `prefix/node_modules` folder to -your NODE_PATH environment variable. +If you wish to `require()` a package, then install it locally. ### Executables @@ -58,27 +63,27 @@ program, and are deleted upon successful exit. ## More Information -When you run `npm install foo@1.2.3` it downloads and builds the -package, and then, if there is a package.json file in the current -working directory, it copies it to `$PWD/node_modules/foo`, so that your -current package will get it when you do `require("foo")`. +When doing local installings, npm first tries to find an appropriate +`prefix` folder. This is so that `npm install foo@1.2.3` will install +to the sensible root of your package, even if you happen to have `cd`ed +into some other folder. + +Starting at the $PWD, npm will walk up the folder tree checking for a +folder that contains either a `package.json` file, or a `node_modules` +folder. If such a thing is found, then that is treated as the effective +"current directory" for the purpose of running npm commands. (This +behavior is inspired by and similar to git's .git-folder seeking +logic when running git commands in a working dir.) -When this is done, it also installs all of foo's dependencies to -`./node_modules/foo/node_modules/`, so that it will get its dependencies -appropriately when it calls `require()`. If foo depends on bar, and bar -depends on baz, then there will also be a -`./node_modules/foo/node_modules/bar/node_modules/baz`, and so on. +If no package root is found, then the current folder is used. -If there is not a package.json in the current working directory, then -npm walks up the working dir parent paths looking for a package.json, -indicating the root of a package, or a node_modules folder, -indicating an npm package deployment location, and then take the party to that -location. This behavior may be suppressed by setting the `seek-root` -config value to false. +When you run `npm install foo@1.2.3`, then the package is loaded into +the cache, and then unpacked into `./node_modules/foo`. Then, any of +foo's dependencies are similarly unpacked into +`./node_modules/foo/node_modules/...`. -If no package root is found, then a global installation is performed. -The global installation may be supressed by setting the `global` -configuration to false, in which case, the install will fail. +Any bin files are symlinked to `./node_modules/.bin/`, so that they may +be found by npm scripts when necessary. ### Global Installation @@ -86,9 +91,9 @@ If the `global` configuration is set to true, or if it is not explicitly set false and no suitable node_modules folder was found, then npm will install packages "globally". -This means that the module contents are symlinked (or, on windows, -copied) from `root///package` to -`root/node_modules/`. +For global installation, packages are installed roughly the same way, +but the module root is `/usr/local/lib/node_modules`, and bin files are +linked to `/usr/local/bin` instead of `./node_modules/.bin`. ### Cycles, Conflicts, and Folder Parsimony @@ -131,33 +136,30 @@ In this case, we might expect a folder structure like this: foo +-- node_modules - +-- bar (1.2.3) + +-- bar (1.2.3) <---[A] | +-- node_modules - | | `-- baz (2.0.2) + | | `-- baz (2.0.2) <---[B] | | `-- node_modules | | `-- quux (3.2.0) | `-- asdf (2.3.4) - `-- baz (1.2.3) + `-- baz (1.2.3) <---[C] `-- node_modules - `-- quux (3.2.0) - `-- node_modules - `-- bar (1.2.3) - `-- node_modules - `-- asdf (2.3.4) + `-- quux (3.2.0) <---[D] Since foo depends directly on bar@1.2.3 and baz@1.2.3, those are installed in foo's node_modules folder. -Bar has dependencies on baz and asdf, so those are installed in bar's -node_modules folder. Baz has a dependency on quux, so that is installed -in its node_modules folder. +Bar [A] has dependencies on baz and asdf, so those are installed in bar's +node_modules folder. Because it depends on `baz@2.x`, it cannot re-use +the `baz@1.2.3` installed in the parent node_modules folder [C], and +must install its own copy [B]. Underneath bar, the `baz->quux->bar` dependency creates a cycle. -However, because `bar` is already in `quux`'s ancestry, it does not +However, because `bar` is already in `quux`'s ancestry [A], it does not unpack another copy of bar into that folder. -Similarly, underneath `foo->baz`, the same cycle is gradually prevented -because `bar`'s `quux` dependency is satisfied by its parent folder. +Underneath `foo->baz` [C], quux's [D] folder tree is empty, because its +dependnecy on bar is satisfied by the parent folder copy installed at [A]. For a graphical breakdown of what is installed where, use `npm ls`. -- cgit v1.2.3