dependency-tree
Version:
Get the dependency tree of a module
120 lines (92 loc) • 6.07 kB
Markdown
# dependency-tree
[](https://github.com/dependents/node-dependency-tree/actions/workflows/ci.yml?query=branch%3Amain)
[](https://www.npmjs.com/package/dependency-tree)
[](https://www.npmjs.com/package/dependency-tree)
> Get the dependency tree of a module
```sh
npm install dependency-tree
```
* Supports JS (AMD, CommonJS, ES6), TypeScript, and CSS preprocessors (PostCSS, Sass, Stylus, Less) - any type handled by [precinct](https://github.com/dependents/node-precinct)
- CommonJS: third-party (npm) dependencies are included by default
- Path resolution is handled by [filing-cabinet](https://github.com/dependents/node-filing-cabinet); RequireJS and webpack loaders are supported
* Core Node built-ins (assert, path, fs, etc.) are excluded by default
## Usage
```js
// ESM
import dependencyTree from 'dependency-tree';
// CommonJS
const { default: dependencyTree } = require('dependency-tree');
// Returns a nested dependency tree object for the given file
const tree = dependencyTree({
filename: 'path/to/a/file',
directory: 'path/to/all/files',
requireConfig: 'path/to/requirejs/config', // optional
webpackConfig: 'path/to/webpack/config', // optional
tsConfig: 'path/to/typescript/config', // optional
nodeModulesConfig: {
entry: 'module'
}, // optional
filter: (dependencyPath, parentPath) => !dependencyPath.includes('node_modules'), // optional
nonExistent: [], // optional
noTypeDefinitions: false // optional
});
// Returns a post-order flat list of absolute paths (dependencies before dependents).
// Useful as a concatenation order for bundling.
const list = dependencyTree.toList({
filename: 'path/to/a/file',
directory: 'path/to/all/files'
});
```
### Options
| Option | Type | Default | Description |
|---|---|---|---|
| `filename` | `string` | - | **Required.** Absolute path to the entry file |
| `directory` | `string` | - | **Required.** Root directory used to resolve relative paths |
| `root` | `string` | `undefined` | Alias for `directory` |
| `requireConfig` | `string` | `undefined` | Path to a RequireJS config for AMD modules (resolves aliased paths) |
| `config` | `string` | `undefined` | Alias for `requireConfig` |
| `webpackConfig` | `string` | `undefined` | Path to a webpack config for aliased modules |
| `tsConfig` | `string \| object` | `undefined` | Path to a TypeScript config file, or a preloaded config object |
| `tsConfigPath` | `string` | `undefined` | Virtual path for the TypeScript config when `tsConfig` is an object. Required for [Path Mapping](https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping); ignored when `tsConfig` is a string path |
| `nodeModulesConfig` | `object` | `undefined` | Config for resolving `node_modules` entry files (e.g. `{ entry: 'module' }`) |
| `visited` | `object` | `{}` | Memoization cache (filename to subtree) to skip already-processed files |
| `nonExistent` | `string[]` | `[]` | Array populated with partial paths that could not be resolved |
| `isListForm` | `boolean` | `false` | Return a flat post-order list of paths instead of a nested tree (same as calling `dependencyTree.toList()`) |
| `filter` | `(dependencyPath: string, parentPath: string) => boolean` | `undefined` | Return `true` to include a dependency (and its subtree) in the tree |
| `detectiveConfig` | `object` | `{}` | Options passed to [precinct](https://github.com/dependents/node-precinct#usage) for dependency extraction - e.g. `{ amd: { skipLazyLoaded: true } }`, `{ ts: { skipTypeImports: true } }` |
| `detective` | `object` | `{}` | Alias for `detectiveConfig` |
| `noTypeDefinitions` | `boolean` | `false` | Resolve TypeScript imports to `*.js` instead of `*.d.ts` |
### Output format
The default output is a nested object where every key is an absolute file path and the value is its own subtree:
```js
{
'/path/to/a.js': {
'/path/to/b.js': {
'/path/to/d.js': {},
'/path/to/e.js': {}
},
'/path/to/c.js': {
'/path/to/f.js': {},
'/path/to/g.js': {}
}
}
}
```
This format was designed for visual representation in the [Dependents](https://github.com/mrjoelkemp/sublime-dependents) plugin.
### CLI
Requires a global install: `npm install -g dependency-tree`
```
dependency-tree --directory=path/to/files [--list-form] [--es6-mixed-imports] [-c path/to/require/config] [-w path/to/webpack/config] filename
```
Prints the dependency tree as JSON. Use `--list-form` to print one path per line instead.
## How it works
dependency-tree passes the entry file to [precinct](https://github.com/dependents/node-precinct/) to extract raw dependency strings, then passes each to [filing-cabinet](https://github.com/dependents/node-filing-cabinet) to resolve them to real filesystem paths, and recurses until the full tree is built.
Precinct generates an AST via [node-source-walk](https://github.com/dependents/node-source-walk), detects the module format (CommonJS, AMD, or ES6), and delegates to the appropriate detective to extract dependency declarations.
Filing-cabinet reuses that AST to detect the module format again, then delegates to the right resolver - necessary because AMD supports path aliasing via a RequireJS config, while CommonJS has its own resolution algorithm. The resolver returns an absolute path, which dependency-tree then recurses into.
## FAQ
### Why aren't some dependencies being detected?
Bugs in [precinct](https://github.com/dependents/node-precinct) or an incomplete `requireConfig`/`webpackConfig`/`tsConfig` are the most common causes. Any path that could not be resolved is appended to the array passed as `nonExistent`.
For detailed resolution logs, set `NODE_DEBUG=*` when using the CLI:
```sh
NODE_DEBUG=* dependency-tree -w path/to/webpack.config.json path/to/a/file
```