Dependency-cruiser sports some filters that enable you to leave out certain parts of dependency-trees you're not particularly interested in. They work from the command line (as --do-not-follow, --include-only, --focus and --exclude respectively) but you can also specify them in the configuration file.
On the command line you can pass a single regular expression for each of them. The filters will use that to match against the (resolved) paths of modules in your dependency tree.
The configuration file gives a little bit more flexibility. Apart from the path you can specify additional properties, and pass an array of regular expressions (which in some instances will enhance legibility).
You can pass the path in one of three ways:
As a single regular expression:
options: {
includeOnly: {
path: "^bin|^src|^test|^packages";
}
}
As an array of regular expressions:
options: {
includeOnly: {
path: ["^bin", "^src", "^test", "^packages"];
}
}
Or in shorthand:
options: {
includeOnly: ["^bin", "^src", "^test", "^packages"];
}
The next sections contain details on what each filter does and what extra attributes you can pass.
🐚 command line option equivalent:
--do-not-follow
(string values passed to 'path' only)
If you do want to see certain modules in your reports, but are not interested
in these modules' dependencies, you'd pass the regular expression for those
modules to the doNotFollow
option. A typical pattern you'd
use with this is "node_modules":
"options": {
"doNotFollow": {
"path": "node_modules"
}
}
It's not possible to use this on the command line
It is possible to specify a regular expression for files that dependency-cruiser should cruise, but not follow any further. In the options section you can restrict what gets cruised by specifying dependency types. So if e.g. you don't want dependency-cruiser to follow external dependencies, instead of specifying the "node_modules" path:
"options": {
"doNotFollow": {
// "path": "node_modules",
"dependencyTypes": [
"npm",
"npm-dev",
"npm-optional",
"npm-peer",
"npm-bundled"
]
}
}
There's a few steps dependency-cruiser takes when you fire it of:
- gather all files specified as an argument, filtering out the stuff in
exclude
anddoNotFollow
and that which is not inincludeOnly
.- starting from the gathered files: crawl all dependencies it can find. Crawling stops when a module matches
doNotFollow
rule or a modules' dependency matches eitherexclude
or does not matchincludeOnly
.- apply any rules over the result & report it.
So in the first step
doNotFollow
behaves itself exactly likeexclude
would. Only in the second step it allows files matching its pattern to be visited (but not followed any further).This means dependency-cruise will encounter files matching
doNotFollow
but only when they are dependencies of other modules. This a.o. prevents unexpected behaviour where specifying node modules asdoNotFollow
pattern would still traverse all node_modules when the node_modules were part of the arguments e.g. indepcruise --do-not-follow node_modules --validate -- src test node_modules
or, more subtly withdepcruise --don-not-follow node_modules -- validate -- .
.
🐚 command line option equivalent:
--include-only
In the includeOnly
option you can pass a regular expression of all file paths
dependency-cruiser should include in a cruise. It will discard all files
not matching the includeOnly
pattern.
This can be handy if you want to make an overview of only your internal application
structure. E.g. to only take modules into account that are in the src
tree (and
exclude all node_modules, core modules and modules otherwise outside it):
"options": {
"includeOnly": "^src/"
}
If you specify both an includeOnly and an exclude (see below), dependency-cruiser takes them both into account.
🐚 command line option equivalent:
--focus
Just like the includeOnly
option, focus
takes a regular expressions you want
dependency-cruiser to show in its output. In addition dependency-cruiser will
include all neighbours of those modules; direct dependencies and direct
dependents.
This can be useful if you just want to focus on one part of your application and how it interacts with the outside world.
Add a focus
attribute in your options section. You will typically want to use
this option in conjunction with one of the other filtering options, like
doNotFollow or includeOnly as that will speed up the rendition quite
a lot.
doNotFollow, includeOnly and exclude can run before dependency-cruiser does any static analysis, so dependency-cruiser applies as early on in the process as it can so it can prevent having to read files from disk (which is expensive).
It can only determine the modules in focus and their neighbours after applying static analysis, though, as only then it knows what the relationships between the modules are.
Example configuration:
{
"options": {
"includeOnly": "^src/",
"focus": "^src/main/"
}
}
sample command line invocation and graphical output
depcruise -c focus.config.json -T dot | dot -T svg > focus.svg
When dependency-cruiser applies focus on modules, it provides each module with
a matchesFocus
attribute, which is either true
for modules in focus or
false
for the neighbours. You can use this attribute e.g. in your
dot theme.
sample dot theme that uses matchesFocus + graphical output
{
"options": {
"includeOnly": "^src/",
"focus": "^src/main/",
"reporterOptions": {
"dot": {
"collapsePattern": "^node_modules/[^/]+/",
"theme": {
"graph": {
"splines": "ortho"
},
"modules": [
{
"criteria": { "matchesFocus": true },
"attributes": {
"fillcolor": "lime"
}
},
{
"criteria": { "matchesFocus": false },
"attributes": {
"fillcolor": "lightgray",
"fontcolor": "gray"
}
}
]
}
}
}
}
}
When run...
depcruise -c snazzy-focus.config.json -T dot | dot -T svg > snazzy-focus.svg
...it'll look something like this:
🐚 command line option equivalent:
--exclude
(string values passed to 'path' only)
If you don't want to see certain modules in your report (or not have them
validated), you can exclude them by passing a regular expression to the
exclude
. E.g. to exclude node_modules
from being scanned altogether:
"options": {
"exclude": {
"path": "node_modules"
}
}
Because it's regular expressions, you can do more interesting stuff here as well. To exclude all modules with a file path starting with coverage, test or node_modules, you could do this:
"options": {
"exclude": {
"path": "^(coverage|test|node_modules)"
}
}
It's also possible to exclude dependencies on other properties than the (resolved) paths
at either end of them. To exclude all dependencies that result of an (ECMAScript)
dynamic import from being included in a cruise, you can use the dynamic
attribute:
"options": {
"exclude": {
"dynamic": true
}
}
Other attributes might come in future releases
🐚 command line option equivalent
--collapse
As this is an option that is probably typically used from the command line it's described primarily over there.
🐚 command line option equivalent:
--max-depth
Only cruise the specified depth, counting from the specified root-module(s). This command is mostly useful in combination with visualisation output like dot to keep the generated output to a manageable size.
💡 If you use this to get a high level overview of your dependencies, be sure to check out the archi reporter. That's more flexible, while still taking into account all your rules and dependencies. You can also consider the collapse option for this.
This will cruise the dependencies of each file directly in the src folder, up to a depth of 1:
...
"maxDepth": 1
...
With "maxDepth": 2
it'll look like this:
And with "maxDepth": 3
like this:
💡 The
maxDepth
option is there to help with visualising. If your goal is to validate this option is best left alone as you'll miss a dependency or two otherwise.
🐚 command line option equivalent:
--module-systems
Here you can pass a list of module systems dependency-cruiser should use
to detect dependencies. It defaults to ["amd", "cjs", "es6", "tsd]
The
'module systems' dependency-cruiser supports:
System | Meaning |
---|---|
amd |
Asynchronous Module Definition as used by a.o. RequireJS |
cjs |
Common js as popularised by node.js which uses the require function to include other modules |
es6 |
modules as defined for ECMAScript 6 in 2015 in Emma-262, with proper import and export statements |
tsd |
TypeScript 'triple slash directives' |
🐚 command line option equivalent:
--ts-pre-compilation-deps
By default dependency-cruiser does not take dependencies between typescript modules into account that don't exist after compilation to JavaScript.
Switch this option to true
if you do want to take them into account
(as a bonus this will make cruising typescript code bases faster).
If you want to define rules on whether dependencies exist only
before compilation or also after (with preCompilationOnly
)
you can pass the value "specify"
to this option. Only do this if
you really need it as it will impact cruise speed. You can only use the
"specify"
value within dependency-cruiser configurations (not from the
command line).
Pre-compilation dependencies example: only importing a type
As the JavaScript doesn't really know about types, dependencies on types only exist before, but not after compile time.a.ts
exports an interface ...
import { B } from "./b";
export interface A {
foo: string;
}
const b = new B();
... and b.ts
uses that interface:
import { A } from "./a";
export class B {}
const a: A = { foo: "foo" };
After compilation b.js
looks like this:
// import omitted as it only contained a reference to a type
export class B {}
const a = { foo: "foo" }; // no type refer
Normally, without tsPreCompilationDeps
the output will
look like this:
With tsPreCompilationDeps
the dependency graph does include the
dependency-on-a-type-only from b.ts
to a.ts
:
Pre-compilation dependencies example: import without use
Similarly, if you import something, but don't use it, the dependency only exists before compilation. Take for example these two typescript modules:
a.ts
:
import { B } from "./b";
export class A {}
b.ts
:
export class B {}
As a.ts
uses none of the imports from b, the typescript
compiler will omit them when compiling and yield this for a.js
:
// no imports here anymore...
export class A {}
Hence, without tsPreCompilationDeps
dependency-cruiser's
output will look like this:
... and with tsPreCompilationDeps
like this:
🐚 command line option equivalent: --ts-config
If dependency-cruiser encounters typescript, it compiles it to understand what it
is looking at. If you have compilerOptions
in your tsconfig.json
you think
it should take into account, you can use this option to make it do that.
You might want to do this e.g. if you have baseDir
/ paths
keys in your
tsconfig
, or are using jsx/ tsx outside of a react context.
Dependency-cruiser understands the extends
configuration in tsconfig's so
if you have a hierarchy of configs, you just need to pass the relevant one.
Sample
"options": {
"tsConfig": {
"fileName": "tsconfig.json"
}
}
You can do it even more minimalistically like so (in which case dependency-cruiser will
assume the fileName to be tsconfig.json
)
"options": {
"tsConfig": {}
}
## use the `tsconfig.json` in the current directory into account when looking
## at typescript sources:
depcruise --ts-config --validate -- src
## use `tsconfig.prod.json for the same purpose:
depcruise --ts-config tsconfig.prod.json --validate -- src
- 💡 The configuration file you can pass as an argument to this option is relative to the current working directory.
- 💡 dependency-cruiser currently only looks at the
compilerOptions
key in the tsconfig.json and not at other keys (e.g.files
,include
andexclude
). - 💡 If you happen to use a
jsconfig.json
you can pass that as well as the syntax of thecompilerOptions
key is the same for both.
🐚 there is no command line equivalent for this at the moment
If you're using babel you can tell dependency-cruiser so by telling it where your babel config lives, like this:
"options": {
"babelConfig": {
"fileName": ".babelrc"
}
}
That way dependency-cruiser will use the babel compiler for its transpilation steps, so if you're using features that are not TC39 stage 4 yet dependency-cruiser will happily analyze these source files for you.
If you just use a babel
key in your package.json pass package.json
as the
babelConfig - dependency-cruiser will sort it out for you.
- 💡 In its current state dependency-cruiser will assume that all JavaScript and TypeScript sources it parses need to go through the babel compiler (regardless of the extension). This will cover the majority of the use cases for babel, but raise an issue if you need this to be configurable.
- 💡 Dependency-cruiser can process json (/ json5) configurations, either in a separate file or as a key in your package.json. It can also process .js and .cjs configurations, as long as they're commonjs modules and export a simple javascript object. JavaScript configurations that export a function, and/ or that are es modules might be supported in a later stage.
- 💡 Auto detection in --init looks at some of the likely suspects for babel configs - package.json (only if it contains a babel key), .babelrc, .babelrc.json, babel.config.json and any other file with babel in the name that ends on json or json5. - The feature currently works with babel versions >=7.0.0
⚠️ Babel support is currently an experimental feature. This means it is thoroughly tested, works well as far as we could determine. It also means dependency-cruiser won't get a major version bump for little changes that for regular features might be considered breaking (think of more precise module system determination).- 🚧 The current implementation of babel support is robust, but can be more efficient. It's on the roadmap, but as it's not entirely trivial it may take some time. The implementation will be feature switched to guarantee stability.
🐚 command line option equivalent:
--webpack-config
passingenv
andarguments
is only available in the configuration file's options
Dependency-cruiser will pluck the resolve
key from the webpack configuration
you pass here and will use that information to resolve files on disk.
"options": {
"webpackConfig": {
"fileName": "webpack.config.js"
}
}
Or, shorter, to let dependency-cruiser pick the default webpack.config.js all by itself:
"options": {
"webpackConfig": {}
}
If your webpack configuration exports a function that takes parameters, you can provide the parameters like so:
"options": {
"webpackConfig": {
"fileName": "webpack.config.js",
"env": { "production": true },
"arguments": { "mode": "production" }
}
}
- 💡 The configuration file you can pass as an argument to this option is relative to the current working directory.
- 💡 If your webpack config exports an array of configurations, dependency-cruiser will only use the resolve options of the first configuration in that array.
- 💡 For more information check out the the webpack resolve documentation.
🐚 there is no command line equivalent for this
This options is deprecated as per version 9.21.3; it's not necessary anymore as detection now happens automatically (enhanced_resolve supports it out of the box.)
In versions before 9.21.3 you could set it to use yarn's Plug'n'Play to resolve external modules; setting the
externalModuleResolutionStrategy
attribute toyarn-pnp
would get you set for that - the default wasnode_modules
🐚 command line option equivalent:
--prefix
If you want the links in the svg output to have a prefix (say,
https://github.com/you/yourrepo/tree/master/
) so when you click them you'll
open the link on GitHub instead of the local file - pass that in the
prefix
option, e.g.:
...
prefix: "https://github.com/sverweij/dependency-cruiser/tree/develop/"
...
Any URL works, so you can also use it to make sure links always open in your favourite editor. Here's an example for visual studio code:
...
prefix: `vscode://file/${process.cwd()}/`,
...
💡 Make sure the prefix ends on a
/
.
🐚 there is no command line equivalent for this at the moment
By default dependency-cruiser will take the current working directory to start a cruise from. If you want to alter that you can pass it in this attribute.
In the reporterOptions
attribute you can pass things to reporters to influence
their behaviour - for reporters that support this.
Most representational aspects of the 'dot' reporter are customizable:
- On a global level, affecting all rendered modules and dependencies with
graph
,node
andedge
. - Conditional - only affecting modules (or dependencies) that meet the criteria
you specify with
modules
anddependencies
.- You can use any module attribute and any dependency attribute for dependencies.
- For attributes you can use anything GraphViz dot can understand as an attribute (see their attributes documentation for a complete overview).
The criteria are evaluated top to bottom:
- Criteria higher up get precedence over the ones lower down.
- Criteria in the configuration file take precedence over the default ones.
For an extensive example you can have a look at the default theme dependency-cruiser ships with - default-theme.json.
As a base, take this part of dependency-cruisers code:
base.config.js
module.exports = {
options: {
includeOnly: "^src/main",
exclude: "/filesAndDirs/",
},
};
The default template, with tweaks to get an 'engineering' like look (and all
file names ending on .json
a cylindrical look with a soft gradient):
engineering.config.js
module.exports = {
extends: "./base.config.js",
options: {
reporterOptions: {
dot: {
theme: {
replace: false,
graph: {
bgcolor: "dodgerblue",
color: "white",
fontcolor: "white",
fillcolor: "transparent",
splines: "ortho",
},
node: {
color: "white",
fillcolor: "#ffffff33",
fontcolor: "white",
},
edge: {
arrowhead: "vee",
arrowsize: "0.5",
penwidth: "1.0",
color: "white",
fontcolor: "white",
},
modules: [
{
criteria: { source: "\\.json$" },
attributes: {
shape: "cylinder",
fillcolor: "#ffffff33:#ffffff88",
},
},
{
criteria: { coreModule: true },
attributes: {
color: "white",
fillcolor: "#ffffff33",
fontcolor: "white",
},
},
],
dependencies: [
{
criteria: { resolved: "\\.json$" },
attributes: { arrowhead: "obox" },
},
],
},
},
},
},
};
To shift the dependency graph from a horizontal orientation to a vertical one, set
the global graph attribute rankdir
to TD
(top down):
vertical.config.js
module.exports = {
extends: "./base.config.js",
options: {
reporterOptions: {
dot: {
theme: {
graph: { rankdir: "TD" },
},
},
},
},
};
To get output without any attributes and no conditional colouring you can order
the default theme to be replaced by flipping the replace
attribute to true
.
bare
module.exports = {
extends: "./base.config.js",
options: {
reporterOptions: {
dot: {
theme: {
replace: true,
},
},
},
},
};
The dot reporter also supports the collapsePattern
option originally created
for the archi reporter, which summarizes modules matching the pattern
to one node in the output. For the dot
reporter the default is to not summarize
anything, but you can make it do so anyway. A good candidate is the node_modules
folder (provided you want that in your graph)
module.exports = {
options: {
reporterOptions: {
dot: {
// collapse onto folders one step below node_modules:
collapsePattern: "^(node_modules/[^/]+)",
},
},
},
};
The collapsePattern also accepts an array of regular-expressions-in-a-string to be consistent with how other regular expressions in the configuration file are handled.
The 'customizable dot' (cdot
) or 'archi' reporter exists to make high level
dependency overviews. Out of the box it recognises structures that summarise
to folders directly under packages, src, lib, and node_modules. You can
adapt this behaviour by passing a collapsePattern to the archi reporterOptions
in your dependency-cruiser configurations e.g. like so:
module.exports = {
options: {
reporterOptions: {
archi: {
collapsePattern: "^(src/[^/]+|bin)",
},
},
},
};
It also accepts the same theme
option dot
does. If you don't specify a theme,
it'll use the one specified for dot
or the default one if that one isn't
specified either.
With the above collapsePattern and a custom dot scheme, the archi report for dependency-cruiser looks like this:
Modules collapsed in this fashion get the special attribute
consolidated
so they're easy to distinguish in a.o. themes. The default theme makes them abox3d
shape (as you can see above) but if you want to use other attributes you can use the power of the theme mechanism to use your own e.g.// ... reporterOptions: { archi: { // ... theme: { modules: [ { criteria: { collapsed: true }, attributes: { shape: "tab" } } ] } } // ...
The level of detail you want to see in a visual representation can differ (quite a bit) from the detail you need for validation. This is the reason other graphical reporters exist as well, which collapse modules and their dependencies to either folders (ddot), or to a level you specify (archi).
With filters you can prune the dependency tree the dot reporter shows. It works on top of the cruise-level filters (includeOnly, exclude, focus and doNotFollow) and only for the reporter you configured it for.
The filters specified in the dot reporterOptions act as a fall back for the archi and ddot reporterOptions. This is because we found that often you want the same pruning for all visualisations.
The filters the reporterOptions.dot.filters support are includeOnly, exclude and focus. Currently they only support the path attribute (which, just like the ones on top cruise level accepts either a regular-expression-as-a-string or an array of them).
Example:
module.exports = {
options: {
// this global doNotFollow option makes sure that dependency-cruiser
// doesn't crawl any further when it encounters something with node_modules
// in the name. The encountered module will be in the dependency-tree however
doNotFollow: "node_modules",
reporterOptions: {
dot: {
filters: {
// makes sure only things in the src tree end up in the dot
// report, and not things in node_modules, test or bin
includeOnly: {
path: "^src",
},
},
},
},
},
};
Why would you use this over an extra cruise over the modules? If you have a
lot of modules a cruise can take some time. Running a reporter takes relatively
little time. You can leverage this knowledge by saving the results as json
and then (with depcruise-fmt
) run the various
reporters over it. E.g.
# depcruise reads all specified modules from disk and parses them to infer
# dependencies. For big repos this can take a while
depcruise src bin test -T json -c > results.json
# depcruise-fmt just reads the result of a cruise and emits a report
# on it, so it doesn't need to do the expensive disk access & parse
# step. These three formatting steps together will take a lot less
# than even one cruise:
depcruise-fmt -T dot results.json | dot -T svg > module-graph.svg
depcruise-fmt -T archi results.json | dot -T svg > high-level-graph.svg
depcruise-fmt -e -T err results.json
Note: as of version 9.12.0 depcruise-fmt has filters as command line options that have the same effect, work on all reporters and might give you more flexibility.
depcruise-fmt -T dot results.json --include-only "^packages/search" | dot -T svg > search.svg depcruise-fmt -T dot results.json --include-only "^packages/ancillaries" | dot -T svg > ancillaries.svg depcruise-fmt -T dot results.json --include-only "^packages/checkout" | dot -T svg > checkout.svg
When you instructed dependency-cruiser to calculate metrics, with the showMetrics switch you can influence whether you want to show them in the graph or not (which is also the default).
module.exports = {
options: {
reporterOptions: {
dot: {
showMetrics: true,
},
},
},
};
This currently shows the instability metric next to the filename, e.g for the
dot
reporter like so:
The anonymous reporter has a wordlist
option to pass it a list of words to use
to replace path elements with before it starts to generate random names. If you
use the anonymous report a lot it can be beneficial to use a list of words so the
output is repeatable (and easier to read).
{
"options": {
"reporterOptions": {
"anon": {
"wordlist": [
"foo",
"bar",
"baz",
"qux",
"grault",
"garply",
"waldo",
"fred"
]
}
}
}
}
You're likely to need a lot of words to cover all your path elements if you want to prevent random names as much as possible. There's word lists in the wild that work exceptionally well - in the past I have used Sindre Sorhus' mnemonic-words list for this. If you use JavaScript as the configuration file format you can simply require it:
const mnemonicWords = require('mnemonic-words');
module.exports = {
// ...
options: {
reporterOptions:
anon: {
wordlist: mnemonicWords
}
}
}
By default the metrics reporter emits instability metrics for all modules and folders, ordered by instability (descending). If you want to see less, or use a different sort order, you can tweak that with the metrics reporterOptions.
hideModules
: switch totrue
if you only want to see instability metrics for folders. Defaults tofalse
.hideFolders
: switch totrue
if you only want to see instability metrics for modules. Defaults tofalse
.orderBy
: with this you can specify how the metrics reporter orders its output. Defaults toinstability
. Possible valuesname
,moduleCount
,afferentCouplings
,efferentCouplings
,instability
.
module.exports = {
// ...
options: {
reporterOptions: {
metrics: {
hideModules: true, // hides the modules from the metrics reporter output
// hideFolders: true, // would hide folders from the metrics reporter output
orderBy: "name", // possible values: name, moduleCount, afferentCouplings, efferentCouplings, instability
},
},
},
};
command line option equivalent:
--preserve-symlinks
Whether to leave symlinks as is or resolve them to their realpath. This option
defaults to false
- which is also nodejs' default behaviour since release 6.
If combinedDependencies
is on false
(the default) dependency-cruiser will
search for a package.json
closest up from the source file it investigates.
This is the behaviour you expect in a regular repo and in mono repos with
independent packages. When in doubt keep this switch out of your config or
set it to false
.
Example
- monodash/
- package.json
- packages/
- begindash/
- package.json <- only look in this one
- src/
- index.ts
- begindash/
With combinedDependencies
on true
dependency-cruiser will merge dependencies
from package.json
s from closest up from the source file until the place you
started the cruise (typically the root of your monorepo). It 'll give
precedence to the dependencies declared in the package.json closest to
the file it investigates:
- monodash/
- package.json <- look in this one as well; merge it into the one down the tree
- packages/
- begindash/
- package.json <- look in this one
- src/
- index.ts
In some situations you might not be able to use the require
function
directly or at all. E.g. when you're not sure a module is present and
want to have a fallback (semver-try-require).
Or because require in your environment is used for something else and
you needed to redefine require (const want = require; const whoa = want('whoadash')
).
Or because you're in AMD and you named the require parameter something
else because of a company wide standard to do so.
In each of these cases you can still infer dependencies with the exoticRequireStrings option by adding an exoticRequireStrings array to the options in your dependency cruiser config.
E.g.:
"options": {
"exoticRequireStrings": ["want", "tryRequire", "window.require"]
}
The first step dependency-cruiser takes is to scan files and folders matching
the arguments you passed it for files it can parse - typically TypeScript or
JavaScript sources. Only in a next step it considers other file types, like
when you include a picture from a .jsx
. This approach means dependency-cruiser
only finds these file types when they're reachable from parseable file types.
If you want to run orphan or reachability rules against these file types, however
you might want include them in the first scan already. To do so you can pass
their extensions in an extraExtensionsToScan
array, like so:
"options": {
"extraExtensionsToScan": [".json", ".jpg", ".webp", ".png"]
}
dependency-cruiser will take special care not to even read these files as it can't parse them anyway, and skipping them saves (sometimes a lot) of time. This also means that if you put an extension in the extra extensions to scan dependency-cruiser could have had parsed it won't.
Under the hood dependency-cruiser uses webpack's
enhanced-resolve.
to resolve dependencies to disk. You can influence how dependency-cruiser uses
it directly by passing resolver options in a
webpack config
for most things. If you do need to influence how dependency-cruiser does
its resolution, but don't (want to) have a webpack config, you can use the
enhancedResolveOptions
section to set them.
List of strings to consider as 'exports' fields in package.json. Use ['exports'] when you use packages that use such a field and your environment supports it (e.g. node ^12.19 || >=14.7 or recent versions of webpack).
If you have an exportsFields
attribute in your webpack config, that one will
have precedence over the one specified here.
List of conditions to check for in the exports field. e.g. use ['imports']
if
you're only interested in exposed es6 modules, ['require']
for commonjs, or all
conditions at once (['import', 'require', 'node', 'default']
) if anything goes
for you. Only works when the 'exportsFields' array is non-empty.
If you have an conditionNames
attribute in your webpack config, that one will
have precedence over the one specified here.
List of extensions to scan for when resolving. Typically you want to leave this alone as dependency-cruiser figures out what extensions to scan based on
- what is available in your environment
- in the order your environment (nodejs, typescript) applies the resolution itself.
However, if you want it to scan less you can specify so with the extensions
attribute. E.g. when you're 100% sure you only have typescript & json and
nothing else you can pass ['.ts', '.json']
- which can lead to performance gains
on systems with slow i/o (like ms-windows), especially when your tsconfig
contains paths/ aliasses.
Likely you will not need to use this
We want to have a slightly tighter control over the way enhanced-resolve accesses the file system as with the wrong settings a lot can go wrong. There's one thing you might still want the ability to change though, in a limited number of circumstances and that is the time enhanced resolve's files systems retains resolutions in memory.
With cacheDuration
you can tweak the number of milliseconds
enhanced-resolve's cached
file system should use for cache duration. Typicially you won't have to touch
this - the default works well for repos up to 5000 modules/ 20000 dependencies,
and likely for numbers above as well. If you experience memory problems on a
(humongous) repository you can use the cacheDuration attribute to tame
enhanced-resolve's memory usage by lowering the cache duration trading off against
some (for values over 1000ms) or significant (for values below 500ms) performance.
Dependency-cruiser currently uses 4000ms, and in the past has used 1000ms - both
with good results.
E.g. to set the cache duration to 1337ms, you can use this:
{
// ...
"options": {
// ...
"enhancedResolveOptions": {
"cachedInputFileSystem": {
"cacheDuration": 1337
}
}
// ...
}
}
The cache duration is limited from 0ms (~ don't use a cache) to 1800000ms (0.5h).
The cacheDuration used here overrides any that might be set in webpack configs.
Dependency-cruiser will automatically determine whether it needs to derive dependents.
However, if you want to force them to be derived, you can switch this variable
to true
.
With this EXPERIMENTAL feature you can specify which parser you want to use
as the primary parser: the acorn
one, which handles all things javascript
(commonjs, es-modules, jsx), or one of two parser that can in addition parse
typescript; microsoft's tsc
or the faster and smaller (but slightly less
feature rich) swc
.
swc
and tsc
only work when the compilers (respectivley @core/swc
and
typescript
) are installed in the same spot as dependency-cruiser is. They're
not bundled with dependency-cruiser.