Welcome to mirror list, hosted at ThFree Co, Russian Federation.

new-module-system.1 « future-ideas « man1 - github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 296f1573bae799c0b974fdeb72638ccda3c5b0a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
.\" Generated with Ronnjs/v0.1
.\" http://github.com/kapouer/ronnjs/
.
.TH "NPM\-FOLDERS" "1" "March 2011" "" ""
.
.SH "NAME"
\fBnpm-folders\fR \-\- Folder Structures Used by npm
.
.SH "FUTURE"
This functionality is not yet implemented\.  It is a plan, not reality\.
It is not the map, nor the territory, but a blueprint with blank areas\.
.
.P
In particular, this is the scheme that will be used starting in npm@0\.3,
which will require node@0\.5\.0 or above\.
.
.SH "GOALS"
.
.IP "\(bu" 4
Don\'t splat stuff across the filesystem so much\.  Just specify a single
root location, and be done with it\.
.
.IP "\(bu" 4
Work on windows\.
.
.IP "\(bu" 4
Minimize shim/symlink usage\.
.
.IP "\(bu" 4
Do not rely on any global system path for node modules\.
.
.IP "\(bu" 4
Remove the "activation" concept\.
.
.IP "" 0
.
.SH "DESCRIPTION"
npm metadata lives in the \fBroot\fR setting\.  There is the cache folder,
and the contents of all installed packages\.
.
.P
The default npm root folder is \fB/usr/local/lib/npm\fR\|\.
.
.P
TODO: What should the root folder be on windows?
.
.SS "Cache folder"
The cache folder is a mirror of the data in the registry, as well as a
working space for unpacking and creating tarballs\.
.
.P
Files and folders created in the cache are owned by the executing user,
often "root"\.
.
.P
Files are created with 0666 and folders with 0777, so that they can be
modified by any user\.
.
.IP "\(bu" 4
\fBroot/cache\fR Cache folder
.
.IP "\(bu" 4
\fBroot/cache/foo/cache\.json\fR Expirable cache of registry/foo json data
.
.IP "\(bu" 4
\fBroot/cache/foo/1\.2\.3/package\fR Pristine copy of foo package contents
.
.IP "\(bu" 4
\fBroot/cache/foo/1\.2\.3/package\.tgz\fR tarball of foo@1\.2\.3
.
.IP "" 0
.
.SS "Package folders"
In the npm root folder, package contents are unpacked, built, and then
moved into the desired location\.
.
.IP "\(bu" 4
\fBroot/packages/foo/1\.2\.3\fR Metadata and contents of foo@1\.2\.3
.
.IP "\(bu" 4
\fBroot/packages/foo/1\.2\.3/package\fR Build location of foo@1\.2\.3
.
.IP "\(bu" 4
\fBroot/packages/foo/1\.2\.3/node_modules\fR Links to (or, on windows, copies of)
dependencies of foo@1\.2\.3
.
.IP "\(bu" 4
\fBroot/packages/foo/1\.2\.3/metadata\.json\fR Metadata about the foo package\.
.
.IP "" 0
.
.SS "Installation in `node_modules` Folders"
When you run \fBnpm install foo@1\.2\.3\fR it downloads and builds the
package, and then, if there is a package\.json file in the current
working directory, it copies it to \fB$PWD/node_modules/foo\fR, so that your
current package will get it when you do \fBrequire("foo")\fR\|\.
.
.P
When this is done, it also installs all of foo\'s dependencies to \fB\|\./node_modules/foo/node_modules/\fR, so that it will get its dependencies
appropriately when it calls \fBrequire()\fR\|\.  If foo depends on bar, and bar
depends on baz, then there will also be a \fB\|\./node_modules/foo/node_modules/bar/node_modules/baz\fR, and so on\.
.
.P
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 \fBseek\-root\fR
config value to false\.
.
.P
If no package root is found, then a global installation is performed\.
The global installation may be supressed by setting the \fBglobal\fR
configuration to false, in which case, the install will fail\.
.
.SS "Global Installation"
If the \fBglobal\fR 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"\.
.
.P
This means that the module contents are symlinked (or, on windows,
copied) from \fBroot/<name>/<version>/package\fR to \fBroot/node_modules/<name>\fR\|\.
.
.SS "Installing executables"
When installing globally, executables are linked (or, on windows,
shimmed with a \.bat file) to \fBroot/bin\fR\|\.
.
.P
When doing a
localized installation, executables are linked (or, on windows, shimmed)
to \fB\|\./node_modules/\.bin\fR\|\.  This also applies to the case when a globally
installed package\'s dependents are being installed into it\.  Basically,
whenever writing \fB\|\.\.\./node_modules/foo\fR, and the "foo"
package has an executable named "bar", it\'ll write it to \fB\|\.\.\./node_modules/\.bin/bar\fR\|\.
.
.P
It is up to the user to update their PATH environment variable
appropriately for globally installed executables\.  When running package
lifecycle scripts (for example, to build, start, test, etc\.), npm will
put \fB\|\./node_modules/\.bin\fR as the first item in the PATH environ\.
.
.SS "Installing manpages"
npm will install man pages to \fBroot/share/man\fR\|\.  It is up to the user to
make sure that their man program searches this location\.
.
.SS "Cycles, Conflicts, and Folder Parsimony"
Cycles are handled using the property of node\'s module system that it
walks up the directories looking for node\fImodules folders\.  So, at every
stage, if a package is already installed in an ancestor node\fRmodules
folder, then it is not installed at the current location\.
.
.P
Consider the case above, where \fBfoo \-> bar \-> baz\fR\|\.  Imagine if, in
addition to that, baz depended on bar, so you\'d have: \fBfoo \-> bar \-> baz \-> bar \-> baz \.\.\.\fR\|\.  However, since the folder
structure is: foo/node\fImodules/bar/node\fRmodules/baz, there\'s no need to
put another copy of bar into \.\.\./baz/node\fImodules, since when it calls
require("bar"), it will get the copy that is installed in
foo/node\fRmodules/bar\.
.
.P
This shortcut is only used if the exact same
version would be installed in multiple nested node_modules folders\.  It
is still possible to have \fBa/node_modules/b/node_modules/a\fR if the two
"a" packages are different versions\.  However, without repeating the
exact same package multiple times, an infinite regress will always be
prevented\.
.
.P
Another optimization can be made by installing dependencies at the
highest level possible, below the localized "target" folder\.
.
.P
For example, consider this dependency graph:
.
.IP "" 4
.
.nf
foo
+\-\- bar@1\.2\.3
|   +\-\- baz@2\.x
|   |   `\-\- quux@3\.x
|   `\-\- asdf@*
`\-\- baz@1\.2\.3
    `\-\- quux@3\.x
.
.fi
.
.IP "" 0
.
.P
In this case, we\'d expect a folder structure like this:
.
.IP "" 4
.
.nf
foo
+\-\- node_modules
    +\-\- bar (1\.2\.3)
    |   `\-\- node_modules
    |       `\-\- baz (2\.0\.2)
    +\-\- quux (3\.2\.0)
    +\-\- asdf (0\.2\.5)
    `\-\- baz (1\.2\.3)
.
.fi
.
.IP "" 0
.
.P
Since foo depends directly on bar@1\.2\.3 and baz@1\.2\.3, those are
installed in foo\'s node_modules folder\.
.
.P
Since baz@1\.2\.3 depends on quux@3\.x, a satisfying version is placed in
foo\'s node_modules folder, because there are no conflicts\.
.
.P
Since bar@1\.2\.3 depends on asdf@*, a satisfying version is placed in
foo\'s node\fImodules folder\.  It also depends on baz@2\.x, but this
conflicts with the version already installed in foo\'s node\fRmodules
folder, so it is installed into the node_modules folder under bar@1\.2\.3\.
.
.P
baz@2\.0\.2 depends on quux@3\.x, but this dependency is already satisfied
by the quux version installed in foo\'s node_modules folder, so nothing
further needs to be done\.
.
.SS "Snapshotting"
Whenever the \fBnpm snapshot\fR command is run, the package\.json file is
updated to include the versions of all of the packages in the \fB\|\./node_modules\fR folder as dependencies\.
.
.SS "Publishing"
Upon publishing, npm will look in the node_modules folder\.  If any of
the items there are on the "dependencies" or "devDependencies" list, and
are unmodified copies of the corresponding packages in \fBroot/node_modules/<name>/<version>/package\fR, then they will not be
included in the package tarball\.
.
.P
If the package has been modified, then it is left as\-is, and included in
the package\.
.
.P
This allows a package maintainer to install all of their dependencies
(and dev dependencies) locally, but only publish those items that cannot
be found elsewhere\.
.
.SS "Updating"
npm keeps track of every installation of foo@1\.2\.3 in \fBroot/packages/foo/1\.2\.3/metadata\.json\fR\|\.
.
.P
When updating in a package folder (see algorithm for determining this in
"Installation in \fBnode_modules\fR Folders"), npm updates the packages in
the local folder to the latest versions that are compatible with the
requirements in the package\.json file\.
.
.P
If global is set to \fB"super"\fR, then npm will attempt to update
all copies of packages installed anywhere and everywhere that it is
aware of\.
.
.P
If \fBglobal\fR is set to `true, or implied by not being in a package folder
at the time, then npm will update the globally installed packages\.
.
.P
If you do \fBnpm update foo\fR, and you\'re in a local package folder, but \fBfoo\fR is not installed there, and it \fIis\fR installed globally, then that
will be equivalent to doing \fBnpm update foo \-\-global\fR\|\.
.
.SS "Uninstalling"
Uninstalling works like updating\.
.
.P
If global is set to "super", then it removes all traces from everywhere\.
.
.P
If global is set to "true", or implied, then it removes the global copy\.
.
.P
If global is set to "false", or unset and the command is in a package
folder with a copy of the package being removed, then it removes it from
the local folder\.
.
.SS "Linking"
When \fBnpm link\fR is run without any arguments in a package folder, then a
symbolic link is created from that folder to \fBroot/<name>/LINK\fR\|\.
Additionally, its package dependencies are installed to its
\|\./node_modules folder as necessary\.
.
.P
When \fBnpm link <name>\fR is run in another package folder, a symbolic
link is created from \fBroot/<name>/LINK\fR to \fB\|\./node_modules/<name>\fR, and
its dependencies are also installed if necessary\.  (Generally, it will
not be necessary, as the package will already have its own node_modules
folder containing its dependencies\.)
.
.P
When publishing, linked package dependencies are resolved to their
current state\.  It is assumed that the linked folder was linked for a
reason, and may contain changes required for the proper functioning of
the host program\.
.
.TP
npm link use case
.
.IP "" 4
.
.nf
# create a linked "request" package
cd ~/projects/request
npm link
# now write a program that uses request
mkdir \-p ~/projects/my\-program
cd ~/projects/my\-program
git init
# do your git stuff\.\.\.
npm init
# enter some package\.json values
# now we\'re ready to rock\.
# use redis, but don\'t need bleeding edge\.
npm install redis
# use the linked copy of request
npm link request
# now any changes to ~/projects/request will
# be immediately effective in my\-program when
# I do require("request")
.
.fi
.
.IP "" 0
.
.TP
link on Windows
.Not sure how this will work\.  Maybe linking simply isn\'t possible?