1 | # module-deps
|
2 |
|
3 | walk the dependency graph to generate json output that can be fed into
|
4 | [browser-pack](https://github.com/browserify/browser-pack)
|
5 |
|
6 | [![build status](https://secure.travis-ci.org/browserify/module-deps.png)](http://travis-ci.org/browserify/module-deps)
|
7 |
|
8 | # example
|
9 |
|
10 | ``` js
|
11 | var mdeps = require('module-deps');
|
12 | var JSONStream = require('JSONStream');
|
13 |
|
14 | var md = mdeps();
|
15 | md.pipe(JSONStream.stringify()).pipe(process.stdout);
|
16 | md.end({ file: __dirname + '/files/main.js' });
|
17 | ```
|
18 |
|
19 | output:
|
20 |
|
21 | ```json
|
22 | $ node example/deps.js
|
23 | [
|
24 | {"id":"/home/substack/projects/module-deps/example/files/main.js","source":"var foo = require('./foo');\nconsole.log('main: ' + foo(5));\n","entry":true,"deps":{"./foo":"/home/substack/projects/module-deps/example/files/foo.js"}}
|
25 | ,
|
26 | {"id":"/home/substack/projects/module-deps/example/files/foo.js","source":"var bar = require('./bar');\n\nmodule.exports = function (n) {\n return n * 111 + bar(n);\n};\n","deps":{"./bar":"/home/substack/projects/module-deps/example/files/bar.js"}}
|
27 | ,
|
28 | {"id":"/home/substack/projects/module-deps/example/files/bar.js","source":"module.exports = function (n) {\n return n * 100;\n};\n","deps":{}}
|
29 | ]
|
30 | ```
|
31 |
|
32 | and you can feed this json data into
|
33 | [browser-pack](https://github.com/browserify/browser-pack):
|
34 |
|
35 | ```bash
|
36 | $ node example/deps.js | browser-pack | node
|
37 | main: 1055
|
38 | ```
|
39 |
|
40 | # usage
|
41 |
|
42 | ```
|
43 | usage: module-deps [files]
|
44 |
|
45 | generate json output from each entry file
|
46 |
|
47 | ```
|
48 |
|
49 | # methods
|
50 |
|
51 | ``` js
|
52 | var mdeps = require('module-deps')
|
53 | ```
|
54 |
|
55 | ## var d = mdeps(opts={})
|
56 |
|
57 | Return an object transform stream `d` that expects entry filenames or
|
58 | `{ id: ..., file: ... }` objects as input and produces objects for every
|
59 | dependency from a recursive module traversal as output.
|
60 |
|
61 | Each file in `files` can be a string filename or a stream.
|
62 |
|
63 | Optionally pass in some `opts`:
|
64 |
|
65 | * `opts.transform` - a string or array of string transforms (see below)
|
66 |
|
67 | * `opts.transformKey` - an array path of strings showing where to look in the
|
68 | package.json for source transformations. If falsy, don't look at the
|
69 | package.json at all.
|
70 |
|
71 | * `opts.resolve` - custom resolve function using the
|
72 | `opts.resolve(id, parent, cb)` signature that
|
73 | [browser-resolve](https://github.com/shtylman/node-browser-resolve) has
|
74 |
|
75 | * `opts.detect` - a custom dependency detection function. `opts.detect(source)`
|
76 | should return an array of dependency module names. By default
|
77 | [detective](https://github.com/browserify/detective) is used.
|
78 |
|
79 | * `opts.filter` - a function (id) to skip resolution of some module `id` strings.
|
80 | If defined, `opts.filter(id)` should return truthy for all the ids to include
|
81 | and falsey for all the ids to skip.
|
82 |
|
83 | * `opts.postFilter` - a function (id, file, pkg) that gets called after `id` has
|
84 | been resolved. Return false to skip this file.
|
85 |
|
86 | * `opts.packageFilter` - transform the parsed package.json contents before using
|
87 | the values. `opts.packageFilter(pkg, dir)` should return the new `pkg` object to
|
88 | use.
|
89 |
|
90 | * `opts.noParse` - an array of absolute paths to not parse for dependencies. Use
|
91 | this for large dependencies like jquery or threejs which take forever to parse.
|
92 |
|
93 | * `opts.cache` - an object mapping filenames to file objects to skip costly io
|
94 |
|
95 | * `opts.packageCache` - an object mapping filenames to their parent package.json
|
96 | contents for browser fields, main entries, and transforms
|
97 |
|
98 | * `opts.fileCache` - an object mapping filenames to raw source to avoid reading
|
99 | from disk.
|
100 |
|
101 | * `opts.persistentCache` - a complex cache handler that allows async and persistent
|
102 | caching of data. A `persistentCache` needs to follow this interface:
|
103 | ```js
|
104 | function persistentCache (
|
105 | file, // the path to the file that is loaded
|
106 | id, // the id that is used to reference this file
|
107 | pkg, // the package that this file belongs to fallback
|
108 | fallback, // async fallback handler to be called if the cache doesn't hold the given file
|
109 | cb // callback handler that receives the cache data
|
110 | ) {
|
111 | if (hasError()) {
|
112 | return cb(error) // Pass any error to the callback
|
113 | }
|
114 |
|
115 | var fileData = fs.readFileSync(file)
|
116 | var key = keyFromFile(file, fileData)
|
117 |
|
118 | if (db.has(key)) {
|
119 | return cb(null, {
|
120 | source: db.get(key).toString(),
|
121 | package: pkg, // The package for housekeeping
|
122 | deps: {
|
123 | 'id': // id that is used to reference a required file
|
124 | 'file' // file path to the required file
|
125 | }
|
126 | })
|
127 | }
|
128 | //
|
129 | // The fallback will process the file in case the file is not
|
130 | // in cache.
|
131 | //
|
132 | // Note that if your implementation doesn't need the file data
|
133 | // then you can pass `null` instead of the source and the fallback will
|
134 | // fetch the data by itself.
|
135 | //
|
136 | fallback(fileData, function (error, cacheableEntry) {
|
137 | if (error) {
|
138 | return cb(error)
|
139 | }
|
140 | db.addToCache(key, cacheableEntry)
|
141 | cb(null, cacheableEntry)
|
142 | })
|
143 | }
|
144 | ```
|
145 |
|
146 | * `opts.paths` - array of global paths to search. Defaults to splitting on `':'`
|
147 | in `process.env.NODE_PATH`
|
148 |
|
149 | * `opts.ignoreMissing` - ignore files that failed to resolve
|
150 |
|
151 | # input objects
|
152 |
|
153 | Input objects should be string filenames or objects with these parameters:
|
154 |
|
155 | * `row.file` - filename
|
156 | * `row.entry` - whether to treat this file as an entry point, defaults to
|
157 | `true`. Set to `false` to include this file, but not run it automatically.
|
158 | * `row.expose` - name to be exposed as
|
159 | * `row.noparse` - when true, don't parse the file contents for dependencies
|
160 |
|
161 | or objects can specify transforms:
|
162 |
|
163 | * `row.transform` - string name, path, or function
|
164 | * `row.options` - transform options as an object
|
165 | * `row.global` - boolean, whether the transform is global
|
166 |
|
167 | # output objects
|
168 |
|
169 | Output objects describe files with dependencies. They have these properties:
|
170 |
|
171 | * `row.id` - an identifier for the file, used in the `row.deps` prperty
|
172 | * `row.file` - path to the source file
|
173 | * `row.entry` - true if the file is an entry point
|
174 | * `row.expose` - name to be exposed as
|
175 | * `row.source` - source file content as a string
|
176 | * `row.deps` - object describing dependencies. The keys are strings as used
|
177 | in `require()` calls in the file, and values are the row IDs (file paths)
|
178 | of dependencies.
|
179 |
|
180 | # events
|
181 |
|
182 | ## d.on('transform', function (tr, file) {})
|
183 |
|
184 | Every time a transform is applied to a `file`, a `'transform'` event fires with
|
185 | the instantiated transform stream `tr`.
|
186 |
|
187 | ## d.on('file', function (file) {})
|
188 |
|
189 | Every time a file is read, this event fires with the file path.
|
190 |
|
191 | ## d.on('missing', function (id, parent) {})
|
192 |
|
193 | When `opts.ignoreMissing` is enabled, this event fires for each missing package.
|
194 |
|
195 | ## d.on('package', function (pkg) {})
|
196 |
|
197 | Every time a package is read, this event fires. The directory name of the
|
198 | package is available in `pkg.__dirname`.
|
199 |
|
200 | # transforms
|
201 |
|
202 | module-deps can be configured to run source transformations on files before
|
203 | parsing them for `require()` calls. These transforms are useful if you want to
|
204 | compile a language like [coffeescript](http://coffeescript.org/) on the fly or
|
205 | if you want to load static assets into your bundle by parsing the AST for
|
206 | `fs.readFileSync()` calls.
|
207 |
|
208 | If the transform is a function, it should take the `file` name as an argument
|
209 | and return a through stream that will be written file contents and should output
|
210 | the new transformed file contents.
|
211 |
|
212 | If the transform is a string, it is treated as a module name that will resolve
|
213 | to a module that is expected to follow this format:
|
214 |
|
215 | ``` js
|
216 | var through = require('through2');
|
217 | module.exports = function (file, opts) { return through() };
|
218 | ```
|
219 |
|
220 | You don't necessarily need to use the
|
221 | [through2](https://github.com/rvagg/through2) module to create a
|
222 | readable/writable filter stream for transforming file contents, but this is an
|
223 | easy way to do it.
|
224 |
|
225 | module-deps looks for `require()` calls and adds their arguments as dependencies
|
226 | of a file. Transform streams can emit `'dep'` events to include additional
|
227 | dependencies that are not consumed with `require()`.
|
228 |
|
229 | When you call `mdeps()` with an `opts.transform`, the transformations you
|
230 | specify will not be run for any files in node_modules/. This is because modules
|
231 | you include should be self-contained and not need to worry about guarding
|
232 | themselves against transformations that may happen upstream.
|
233 |
|
234 | Modules can apply their own transformations by setting a transformation pipeline
|
235 | in their package.json at the `opts.transformKey` path. These transformations
|
236 | only apply to the files directly in the module itself, not to the module's
|
237 | dependants nor to its dependencies.
|
238 |
|
239 | ## package.json transformKey
|
240 |
|
241 | Transform keys live at a configurable location in the package.json denoted by
|
242 | the `opts.transformKey` array.
|
243 |
|
244 | For a transformKey of `['foo','bar']`, the transformKey can be a single string
|
245 | (`"fff"`):
|
246 |
|
247 | ``` json
|
248 | {
|
249 | "foo": {
|
250 | "bar": "fff"
|
251 | }
|
252 | }
|
253 | ```
|
254 |
|
255 | or an array of strings (`["fff","ggg"]`):
|
256 |
|
257 | ``` json
|
258 | {
|
259 | "foo": {
|
260 | "bar": ["fff","ggg"]
|
261 | }
|
262 | }
|
263 | ```
|
264 |
|
265 | If you want to pass options to the transforms, you can use a 2-element array
|
266 | inside of the primary array. Here `fff` gets an options object with `{"x":3}`
|
267 | and `ggg` gets `{"y":4}`:
|
268 |
|
269 | ``` json
|
270 | {
|
271 | "foo": {
|
272 | "bar": [["fff",{"x":3}],["ggg",{"y":4}]]
|
273 | }
|
274 | }
|
275 | ```
|
276 |
|
277 | Options sent to the module-deps constructor are also provided under
|
278 | `opts._flags`. These options are sometimes required if your transform
|
279 | needs to do something different when browserify is run in debug mode, for
|
280 | example.
|
281 |
|
282 | # usage
|
283 |
|
284 | ```
|
285 | module-deps [FILES] OPTIONS
|
286 |
|
287 | Generate json output for the entry point FILES.
|
288 |
|
289 | OPTIONS are:
|
290 |
|
291 | -t TRANSFORM Apply a TRANSFORM.
|
292 | -g TRANSFORM Apply a global TRANSFORM.
|
293 |
|
294 | ```
|
295 |
|
296 | # install
|
297 |
|
298 | With [npm](http://npmjs.org), to get the module do:
|
299 |
|
300 | ```
|
301 | npm install module-deps
|
302 | ```
|
303 |
|
304 | and to get the `module-deps` command do:
|
305 |
|
306 | ```
|
307 | npm install -g module-deps
|
308 | ```
|
309 |
|
310 | # license
|
311 |
|
312 | MIT
|